DEV Community

Cover image for Build a CSS Ruler
Mads Stoumann
Mads Stoumann

Posted on

Build a CSS Ruler

I'm currently working on a project, where an editor can easily edit breakpoints, using a group of color-coded, stacked <input type="range">-controls, and a bit of JavaScript:

noruler

While this works, it's easier to visualize the breakpoints, if combined with a ruler:

breakpoints

At first, I hardcoded a ruler, using pixels — but then I thought: “What if the editor wants to define the breakpoints in em or ch — or some other unit?”


Let's look into how we can create a configurable ruler, using CSS backround-image, a bunch of variables — and only a tiny bit of JavaScript for a visual editor.

Our ruler will have two sets of “ticks” — low and tall (we'll look into the numbers later):

ruler-num

Both sets of ticks have some initial Custom Properties:



.ruler {
  /* Low ticks */
  --ruler1-bdw: 1px;
  --ruler1-c:  #BBB;
  --ruler1-h: 8px;
  --ruler1-space: 5;

  /* Tall ticks */
  --ruler2-bdw: 1px;
  --ruler2-c:  #BBB;
  --ruler2-h: 20px;
  --ruler2-space: 50;
}


Enter fullscreen mode Exit fullscreen mode

With these properties, we can create a dynamic background-image:



.ruler {
  background-image:
    linear-gradient(90deg, var(--ruler1-c) 0 var(--ruler1-bdw), transparent 0),
    linear-gradient(90deg, var(--ruler2-c) 0 var(--ruler2-bdw), transparent 0);
}


Enter fullscreen mode Exit fullscreen mode

However, without background-repeat and background-size, we're not seeing anything that resembles a ruler!



.ruler {
  background-repeat: repeat-x;
  background-size:
    calc(var(--ruler-unit) * var(--ruler1-space)) var(--ruler1-h),
    calc(var(--ruler-unit) * var(--ruler2-space)) var(--ruler2-h);
}


Enter fullscreen mode Exit fullscreen mode

And that's almost it! We just need to add background-attachment: fixed, so the ruler will stay in place, when we're scrolling!


Adding numbers:

For the numbers, we'll create a list:



<ul class="ruler-x">
  <li></li><li></li> <!-- repeat -->
</ul>


Enter fullscreen mode Exit fullscreen mode

Each blank <li></li> will be a number in our ruler. The number will be aligned to the bottom of the tall “ticks”:



.ruler-x {
  color: var(--ruler-num-c);
  counter-reset: d 0;
  display: flex;
  font-size: var(--ruler-num-fz);
  height: var(--ruler2-h);
  inset-block-start: 0;
  inset-inline-start: calc(var(--ruler-unit) * var(--ruler2-space));
  line-height: 1;
  list-style: none;
  margin: 0;
  opacity: var(--ruler-x);
  overflow: hidden;
  padding: 0;
  position: fixed;
  width: 100%;
}


Enter fullscreen mode Exit fullscreen mode

We'll use a CSS counter to fill out the numbers, based on the --ruler2-space-property:



.ruler-x li {
  align-self: flex-end;
  counter-increment: d var(--ruler2-space);
  flex: 0 0 calc(var(--ruler-unit) * var(--ruler2-space));
}
.ruler-x li::after {
  content: counter(d);
  line-height: 1;
  padding-inline-start: var(--ruler-num-pi);
}


Enter fullscreen mode Exit fullscreen mode

Creating an Editor

Now, let's create a small editor for our ruler.

We'll use a small JavaScript to update the Custom Properties:



app.addEventListener('input', (e) => {
  const input = e.target;
  const value = input.type === 'checkbox' ? (input.checked ? 1 : 0) : input.value;
  document.body.style.setProperty(input.name, value+(input.dataset.suffix||''));
})


Enter fullscreen mode Exit fullscreen mode

In HTML, add <input>s to <form id="app">, using name for the property to set, value for the value (surprise!) and data-suffix to add any suffix to the value:



<input type="range" name="--ruler1-h" value="8" data-suffix="px">


Enter fullscreen mode Exit fullscreen mode

Repeat for all the properties, you want to be editable.


Demo

Here's a Codepen, where I've added a vertical ruler and an editor, using the technique described above (if you're on iOS, open it full-screen to avoid iframe scrolling-issues):


Bonus: right-to-left

If you want to use the y-axis-ruler with rtl, add a small snippet of CSS:



[dir="rtl"] .ruler {
  background-position: 100% 0;
}


Enter fullscreen mode Exit fullscreen mode

Cover-image from pexels.com

Top comments (5)

Collapse
 
domters profile image
Mike Peters • Edited

I also can share my experience! I recently discovered an amazing online ruler application that can be used on any device, including mobile phones, tablets, and computers. It is incredibly easy to use and is perfect for anyone. The best part is that it is completely free to use and offers a wide range of features, including customizable measurements and easy calibration. Whether you are a web developer or just need a quick and easy way to measure small objects, measure it with a virtual ruler!

Collapse
 
girish1729 profile image
Girish Venkatachalam

I utterly love your implemention. Fantastic.

Thanks.

Collapse
 
madsstoumann profile image
Mads Stoumann

Thx!

Collapse
 
snake89322 profile image
Zehui

Very cool, it's useful for my situation.

Collapse
 
mistafisha profile image
mistafisha

This is awesome, except I think the low-tick spacing option should be "divisions" between big-ticks because that is how rulers really are.