An HTML Ruler With Vanilla JavaScript

Asís García
Trabe
Published in
5 min readJun 8, 2020
Photo by patricia serna on Unsplash

For one of our projects, we have to update a bunch of preexisting React components to make them match a redesign given in Figma. This implies having to adjust margins, paddings, and relative positions, making the “real” components a pixel-perfect replica of the “designed” ones.

The problem with pixel-perfect stuff is that you have to measure your components by the pixel. And pixels are tiny 😅. So, I find myself creating “ruler” divs many times a day. Whenever I need to check some distance or size, I have to open the developer tools, edit some component’s HTML, add a new div and then set some styles on it:

position: absolute;
left: 0;
top: 0;
width: 4px;
height: 40px;
background: lime;

With that ruler div in place, then I tweak its position and size, and use it to check for margins, paddings, and alignment issues.

But that feels really tedious, so I’ve decided to automate the process. And yes, I know there are some ruler extensions in the Chrome Web Store. In fact, I’ve used a ruler extension in the past, but I had to uninstall it. I don’t want to go the extension way again, so I will build the ruler myself.

Also, I see this as an opportunity to build something simple but useful — at least for me — and to do it using vanilla JavaScript: no transpilers, no loaders, no bundlers, no BS (Build Step, of course).

First step: enough with the repetition

As I’ve said, I’m inserting the ruler manually. So the first step is to automate creating and styling the div, and then inserting it into the document:

In the snippet above, the ruler function creates a new div element. The ruler will appear as a semi-transparent red square centered on the page.

The function returns a function to remove the ruler from the page. The snippet ends with a trick so it can be evaluated many times, each time removing the old ruler and creating a new one (this way I can keep tweaking the implementation easily).

Second step: move the ruler around

OK, now inserting the ruler is straightforward. But positioning it next to the element to be measured still needs some manual tweaking of the ruler style.

My first instinct is to use the mouse to drag the ruler into position, so I will add some event handlers:

First things first: in order for the ruler to be draggable, its draggable attribute must be set to true. Then, the drag & drop API events are used to move the ruler:

  1. When the dragstart event is fired on the ruler, the distance between the mouse and the ruler top left corner is captured. We can use it once the drag ends to determine how much to move the upper left corner of the ruler element. We store it as a JSON string, using the setData method.
  2. The dragover event handler is attached to the document, because it’s mandatory for an element to act as a drop target (and we want to drop our ruler anywhere in the document).
  3. Once the drag operation finishes, the drop event is fired and the event handler in the document updates the ruler position. We get the mouse offset position from the dragstart event and we parse it. The final ruler position (that is, its top left corner position) is calculated as the position of the mouse where the drop event fires minus the stored offset.

We also update the removeRuler function to get rid of any event handler once the ruler is gone:

Third step: resize the ruler

Now we can add and remove a ruler, and also move it around using the mouse. The only thing that’s left to do is resizing the ruler, as we still have to do it manually through the developer tools.

For this we are going to use the keyboard, so we need to add a keydown event handler to the ruler element. But for the element to be able to process keyboard events, it has to be focused. So we start by setting a tabIndex and giving the ruler the focus just after it is inserted in the page, and also when clicked:

Now we can define the event handler. And, because adjusting the position of the ruler using the mouse is hard when you need precision, I decided to let the user move the ruler using the keyboard too:

When the user presses one of the cursors or the Vim movement keys (h, j, k, and l), we check whether the control key is also pressed. If it is pressed, we update the ruler size. Otherwise, we update its position.

There is a goodie in there: if the user is holding the shift key, we use 10px increments to resize or move the ruler.

The changeSize and changePosition functions look like this:

We also update the removeRuler function to get rid of the event handler (I know, there’s no need for the handler to be removed, as we are also removing the ruler element, but I prefer being consistent 🤷‍♂):

Fourth step: getting feedback

We can insert a ruler element, move it around with the mouse and move it and resize it using the keyboard. The only thing that’s left is knowing what is the size of the ruler. That’s an important thing, because a ruler without marks is mostly useless 😅.

To do this, we will set the ruler title attribute, so if the mouse stops over the ruler, its size will be displayed in a tooltip. But this is a slow and sometimes frustrating UI, so we will also add a keyboard shortcut to print the size to the console.

First, we define some functions to display the ruler information:

Then we update changeSize so that every time the ruler is resized the title is updated and the information logged to the console:

We update the ruler keydown handler, so we can force the current size to be logged to the console pressing the i key:

Final touches: minor improvements and launching the snippet

Minor improvements

The final code includes some minor improvements:

  1. The ruler has a “tracking mode” that can be toggled pressing the t key. When it is enabled, the ruler will follow your mouse, so you don’t need to find it and drag it.
  2. The ruler can be “rotated” by pressing the r key (this will switch the width and height dimensions).
  3. The ruler can be removed by pressing the Esc key.

Launching the snippet

If you are using Chrome, it turns out that you can save and run snippets of JavaScript from the Command Menu. So I just created a new snippet called “ruler”, I pasted the snippet code, and now I can insert a ruler inside the page just typing cmd-o and then !ruler<enter> 😃.

That’s it: using a pinch of CSS and some event handlers I’ve built my own HTML ruler. I hope you find it as useful as I do.

And now, back to the Build Step 😅.

--

--