loading...
Cover image for Create natural annotations in your HTML doc with Rough Notation. 📝

Create natural annotations in your HTML doc with Rough Notation. 📝

vaibhavkhulbe profile image Vaibhav Khulbe ・7 min read

Want to write a story in your personal portfolio? Or maybe you want to explain some of the nitty-gritty scientific explanations? Usually, we can highlight, emphasize or bold important aspects/text.

But what if we want to add those pen-like markups, some natural hand-drawn underlines on that HTML? This not only is useful for explaining but also feels more like someone used a pen to 'draw' over the document.

Scribble GIF

Yeah, scribbling...but with code. 😎

Say "Hello" to Rough Notation 👋

We can achieve those results using the Rough Notation library.

It lets you create and animate annotations on a web page.

Yes, it does support animations! And the result looks pretty cool. See for yourself what we are about to make:

Rough Notation GIF

Let's start making this quickly!

Installation

Add the following line of Rough Notation CDN to the index.html file:

<script type="module" src="https://unpkg.com/rough-notation?module"></script>

Else, if you're including it on your existing project, here's the command:

npm install --save rough-notation

The HTML

Inside the <body> we have a div which consists of everything we need:

  • Two headings <h1> and <h3>
  • And three paragraphs with the <p> tag.

That's our 'everything!' 😆 As per your liking, add the text content, headings etc. Here's what I have:

<div>
    <h1>Gregor Samsa's Adventures 🎭</h1>
    <h3>Overview of the plot</h3>
    <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown red belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked.
    </p>

    <p>"What's happened to me?" he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples lay spread out on the table - Samsa was a travelling <strong>salesman</strong> - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather... 
   </p>

    <h3>Something unrelated...</h3>

    <p>Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia.</p>
</div>

The CSS

There's not much styling going on here. Just a tad bit of alignment for our div and headings is all we need.

body {
    margin: 0;
    padding: 0;
    font-family: 'Segoe UI', sans-serif;
    line-height: 1.5;
    box-sizing: border-box;
}

div {
    max-width: 600px;
    margin: 0 auto;
    padding: 0 25px;
}

h1, h3 {
    display: inline-block;
}

We're adding some line-height so that the text is more readable, the max-width ensures the content doesn't stretch from left to right all way long. To center it, we say the top and bottom values of the margin should be 0 and let browser automatically calculate for the left and right values. For some breathing space, we add padding values.

As for the headings, make sure they're set to inline-block which will be helpful for drawing those markups later.

Mark it up!

Rough Notation uses two core functions to add one or more markups. These are annotate and annotationGroup.

If you have a single object to mark, use annotate, else for multiple objects/texts we use the annotationGroup function. In our demo, we have multiple objects with one element animating after the other, hence this can be done easily with these two functions.

Step 1: Import

The two functions need to be imported in your JS file from its core module first:

import { annotate, annotationGroup } from 'https://unpkg.com/rough-notation?module';

Step 2: Select the elements to mark

Before any JS code, go back to your HTML. Here we need to add some tags/ids so that the library knows which elements to target. In the demo, we add a <span> to encase "brown", an <em> for "many legs". Similarly, <strong> for "salesman" and id of block for the last paragraph. Now our HTML updates to:

<div>
    <h1>Gregor Samsa's Adventures 🎭</h1>
    <h3>Overview of the plot</h3>
    <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his <span>brown</span> red belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His <em>many legs</em>, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked.</p>

    <p>"What's happened to me?" he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples lay spread out on the table - Samsa was a travelling <strong>salesman</strong> - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather... 
    </p>

    <h3>Something unrelated...</h3>
    <p id="block">Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia.</p>
</div>

Back to our JS then. Here we select all these new elements using the querySelector() method.

Step 3: Add properties

Now we add custom properties to define how the elements should animate and what type of annotation we need. Rough Notation provides various different type of natural hand-like markups from a circle to a highlighter. We can even customise their individual color!

Hence, we create different annotations with the help of annotate() which accepts the type and color of each markup. Feel free to define the type and color. They are all listed here.

Some types like circle and bracket let you add some padding values, strokeWidth and more!

Finish it up with animations!

Finally, we use annotationGroup() to pass in an array of different annotations we made above. Make sure you pass them in they way those elements would animate. The first element of the array (a3) would animate first and the last (a6) one will finish the entire animation sequence.

To actually draw the animation we just defined, use the show() method.

Here's our entire JS code:

import { annotate, annotationGroup } from 'https://unpkg.com/rough-notation?module';

const e1 = document.querySelector('em');
const e2 = document.querySelector('strong');
const e3 = document.querySelector('h1');
const e4 = document.querySelector('h3');
const e5 = document.querySelector('span');
const e6 = document.querySelector('#block');

const a1 = annotate(e1, { type: 'underline', color: 'orangered' });

const a2 = annotate(e2, { type: 'circle', color: 'green', padding: 7 });

const a3 = annotate(e3, { type: 'box', color: 'grey' });

const a4 = annotate(e4, { type: 'highlight', color: 'yellow' });

const a5 = annotate(e5, { type: 'strike-through', color: 'blue' });

const a6 = annotate(e6, { type: 'bracket', color: 'yellowgreen', padding: [2, 10], brackets: ['left'], strokeWidth: 3 })

const animation = annotationGroup([a3, a4, a1, a2, a5, a6]);

animation.show();

There you have it! Looks like someone's drawing with a pen right? If you're stuck somewhere in the code or just want to see the output, I've embedded the Pen below:


Where to next? 🤔

What's amazing is that this library has support for other frameworks/libraries like React, Vue, Angular or Svelte! You can dive here to learn more about the implementation.

Also, support or contribute to this awesome library:

GitHub logo rough-stuff / rough-notation

Create and animate hand-drawn annotations on a web page


Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)



📫 Subscribe to my weekly developer newsletter 📫

PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, here's my Medium profile.

Posted on by:

vaibhavkhulbe profile

Vaibhav Khulbe

@vaibhavkhulbe

👨‍💻 Freelance web developer/designer/writer ✍ | 📧 Subscribe to my weekly dev newsletter with 50+ resources: https://mailchi.mp/f59beeac6b9b/devupdates

Discussion

markdown guide