units – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Tue, 18 Jun 2024 23:40:40 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 units – CSS-Tricks https://css-tricks.com 32 32 45537868 CSS Length Units https://css-tricks.com/css-length-units/ https://css-tricks.com/css-length-units/#comments Mon, 03 Jun 2024 19:22:02 +0000 https://css-tricks.com/?p=375815 A comprehensive guide covering nine types of lengths that CSS uses to size elements in terms of dimensions, space, time, and even sound.


CSS Length Units originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>

Overview

Many CSS properties accept numbers as values. Sometimes those are whole numbers. Sometimes they’re decimals and fractions. Other times, they’re percentages. Whatever they are, the unit that follows a number determines the number’s computed length. And by “length” we mean any sort of distance that can be described as a number, such as the physical dimensions of an element, a measure of time, geometric angles… all kinds of things!

At the time of this writing, the CSS Values and Units Module Level 4 specification defines a bunch of different CSS units — and many of those are relatively new (this pun will make sense later).

Quick Reference

Absolute units
UnitName
cmCentimeters
mmMillimeters
QQuarter-millimeters
inInches
pcPicas
ptPoints
pxPixels
Font units
UnitRelative to…
emThe font size of the element, or its nearest parent container
exThe 0-height of the element’s font 
capThe cap height (the nominal height of capital letters) of the element’s font 
chThe width of the 0 character of the font in use
icThe average width of a full glyph of the font in use, as represented by the “水” (U+6C34) glyph
remThe font-size value that’s set on the root (html) element
lhThe line-height value that’s set on the element 
rlhThe line-height that’s set on the root (html) element 
vw1% of viewport’s width
vh1% of viewport’s height
vi1% of viewport’s size in the root element’s inline axis
vb1% of viewport’s size in the root element’s block axis
vminEqual to 1% of the vw or vh, whichever is smaller
vmaxEqual to 1% of the vw or vh, whichever is larger
Viewport units
vw1% of viewport’s width
vh1% of viewport’s height
vi1% of viewport’s size in the root element’s inline axis
vb1% of viewport’s size in the root element’s block axis
vmin1% of the vw or vh, whichever is smaller
vmax1% of the vw or vh, whichever is larger
Container units
UnitRelative to
cqw1% of a query container’s width
cqh1% of a query container’s height
cqi1% of a query container’s inline size
cqb1% of a query container’s block size
cqminThe smaller value of cqi or cqb
cqmaxThe larger value of cqi or cqb
Angle units
UnitDescription
degThere are 360 degrees in a full circle.
gradThere are 400 gradians in a full circle.
radThere are 2π radians in a full circle.
turnThere is 1 turn in a full circle.
Time units
UnitDescription
sThere are 60 seconds in a minute, but there is no unit for minutes.
msThere are 1,000 milliseconds in a second.
Fractional units
UnitDescription
frOne fraction of the free space in a grid container.
Resolution units
UnitDescription
dpiDots per inch
dpcmDots per centimeter
dppxxDots per pixel unit
Frequency units
UnitDescription
HzRepresents the number of occurrences per second
kHzOne kiloHertz is equal to 1000 Hertz.

Introduction

You’re going to see a lot numbers in CSS. Here are a few examples?

/* Integers */
1

/* Pixels */
14px

/* em */
1.5em

/* rem */
3rem

/* Percentage */
50%

/* Characters */
650ch

/* Viewport units */
100vw
80vh
50dvh

/* Container units */
100cqi
50cqb

While these all mean different things, they essentially do the same thing: define an element’s dimensions in CSS. We need units in CSS because they determine how to size elements on a page, whether it’s the height of a box, the width of an image, the font-size of a heading, the margin between two elements, how long an animation runs, etc. Without them, the browser would have no way of knowing how to apply numbers to an element.

So, what the heck is px? What’s up with this thing called rem? How are these different than other length units? The unit defines what type of number we’re dealing with, and each one does something different, giving us lots of ways to size things in CSS.


Types of numbers

You may think a number is just a number, and you’re not wrong. Numbers are numbers! But we can distinguish between a few different types of numbers, which is helpful context for discussing the different types of units we attach them to since “number” can mean, well, a number of different things.

  • Integers (literally a unit-less number, e.g. 3)
  • Numbers (same as an integer, only measured in decimals, e.g. 3.2)
  • Dimensions (either a number or integer with a unit, e.g. 3.2rem)
  • Ratios (the quotient between two divided numbers, e.g. 3/2)
  • Percentages (e.g. 3%)

Got that? They’re all numbers but with nuances that make them ever-so-slightly different.

From here, we can think of numbers in CSS as falling into two specific types of unitsabsolute and relative. Let’s start things off our deep dive on CSS length units by breaking those down.


Absolute units

An absolute unit is like Bill Murray in the movie Groundhog Day: it’s always the same. In other words, whatever the number is, that’s exactly how it computes in the browser regardless of how other elements are sized.

The most common absolute value you’ll see is the pixel value. It’s sort of hard to define, but a pixel is the smallest building block of a graphical display, like a computer screen. And it’s based on the resolution of the screen. So, if you’re on a super high-resolution screen, a pixel will be smaller than it would be on a low-resolution screen, as the resolution can pack more pixels into a smaller amount of space for higher clarity. But look at the example below. All of the boxes are sized with pixels, so you can get a sense of how large 50px is compared to 250px.

Absolute values are nice in that they are predictable. That could, however, change in some situations, particularly when it comes to zooming. If, say, a user zooms into a page using browser settings, then anything defined with an absolute value is going to increase its absolute size accordingly. So, if the font-size of a paragraph is set to 20px, the paragraph is going to be larger as the user zooms closer into the page. And because zooming is often used to make content more readable, using absolute values that retain their sizing could be a good approach for making pages more accessible by allowing users to zoom things up to a spot that more comfortable to read.

But then again, see Josh Collinsworth’s click-baity, but fantastic, post titled “Why you should never use px to set font-size in CSS” for an exhaustive explanation of how pixels behave when used to set the font-size of an element. It’s a great read to better understand the behavior and limitations of pixel units.

And, hey: pixels are only one of many types of absolute lengths that are available in CSS. In fact, we can group them by the types of things they measure:

Length units

Length units are a little funny because they can technically be either an absolute unit or a relative unit. But we’re discussing them in absolute terms at the moment and will revisit them when we get further along to relative length units.

A length is essentially a dimension, which is any integer proceeded by a unit, according to the list of types of numbers we looked at earlier. And when we talk about dimensions, we’re really talking about the physical size of an element.

UnitName
cmCentimeters
mmMillimeters
QQuarter-millimeters
inInches
pcPicas
ptPoints
pxPixels

What we’re looking at here are the types of units you might use see on a tape measure (e.g., cm and in) or in print design (e.g. pc and pt). They are what they are and what you see is what you get.

Angle units

Angle units are purely geometric. They’re good for setting shape dimensions — like a circle’s radius, setting the direction of a linear-gradient(), or setting the how much we want to rotate() something.

UnitNameDescriptionExample
degDegreesA full circle is equal to 360deg.rotate(180deg)
gradGradiensA full circle is equal to 400grad.rotate(200grad)
radRadiensA full circle is equal to (i.e., 2 × 3.14), or about 6.2832rad.rotate(3.14rad)
turnTurnsA full circle is 1turn, like a bicycle wheel making one full rotation.rotate(.5turn)
Time units

Time units are what you’d expect to find on a clock or watch, but only measure in seconds and milliseconds. Apparently the web cannot be measured in minutes, hours, days, weeks, months, or years. Perhaps we’ll get a new category of “calendar units” at some point, or maybe there’s no good use case for that sort of thing. 🤷‍♂️

UnitNameDescriptionExample
sSecondsOne full minute of time is equal to 60s.animation-duration: 2s
msMillisecondsOne full second of time os equal to 1000ms.animation-duration: 2000ms
Frequency units

You won’t see frequency units used very often and for good reason: they’re not supported by any browser at the time of this writing. But they’re specced to change sound frequency, such as a sound’s pitch. The best I can make of it as it currently stands is that frequencies can be used to manipulate an audio file with a higher or lower pitch measured in hertz and kilohertz.

UnitNameDescriptionExample
HzHertzMeasures the number of frequencies per second<source src="tubthumping.mp3" type="audio/mpeg" frequency="100Hz">
kHzKilohertzA value of 1Hz is equal to 0.001kHz.<source src="tubthumping.mp3" type="audio/mpeg" frequency="0.1kHz">

If you’re wondering what constitutes a “low” pitch from a “high” one, the spec explains it like this:

[W]hen representing sound pitches, 200Hz (or 200hz) is a bass sound, and 6kHz (or 6khz) is a treble sound.

Resolution units

Resolution is how many little dots are packed into a screen — such as the screen you’re looking at right now — where more dots per inch of space improves the clarity and quality of the display. The fewer dots there are, the more pixelated and blurry the display.

Why would you need something like this? Well, it’s great for targeting styles to specific screens that support certain resolutions in a media query.

img {
  max-width: 500px;
}

/* Double the resolution and above */
@media (min-resolution >= 2dppx) {
  img {
    max-width: 100%;
  }
}
UnitNameDescriptionExample
dpiDots per inchThe number of dots packed into one inch of space.@media
(min-resolution: 96dpi) {}
dpcmDots per centimeterThe number of dots packed into one centimeter of space.@media
(min-resolution: 960dpcm) {}
dppx (or x)Dots per pixelThe number of dots packed into one pixel of space.@media
(min-resolution: 1dppx) {}

Interestingly, the specification makes mention of an infinite value that is supported by resolution media queries for targeting screens without resolution constraints. It’s not so much of a “catch-all” value for targeting any sort of screen, but for cases when we’re using the media query range syntax to evaluate whether a certain value is greater than, less than, or equal to it:

For output mediums that have no physical constraints on resolution (such as outputting to vector graphics), this feature must match the infinite value. For the purpose of evaluating this media feature in the range contextinfinite must be treated as larger than any possible <resolution>. (That is, a query like (resolution > 1000dpi)will be true for an infinite media.)

W3C Media Queries Level 4 specification

Relative units

relative unit is extremely well-named because whatever value we use for a relative unit depends on the size of something else. Say we have an HTML element, a <div>, and we give it an absolute height value (not a relative one) of 200px.

<div class="box">
  I am 200 pixels tall
</div>
.box {
  height: 200px;
}

That height will never change. The .box element will be 200px tall no matter what. But let’s say we give the element a relative width (not an absolute one) of 50%.

<div class="box">
  I am 200 pixels tall and 50% wide
</div>
.box {
  height: 200px;
  width: 50%;
}

What happens to our box? It takes up 50%, or half, of the available space on the screen.

See that? Go ahead and open that demo in a new window and change the width of the screen. And notice, too, how the height never changes because it’s an absolute length unit in pixels. The width, meanwhile, is fluidly resized as “50% of the available space” changes with the width of the screen.

That’s what we mean when talking about computed values with relative numbers. A relative number acts sort of like a multiplier that calculates the value used to set a length based on what type of unit it is relative to. So, a value of 3rem is going to wind up becoming a different value when it is computed.

Percentages, like 50%, are only one kind of relative unit. We have many, many others. Once again, it’s helpful to break things out into separate groups to understand the differences just as we did earlier with absolute units.

Percentages

We’ve already discussed percentages in pretty good detail. What makes a percentage relative is that it computes to a number value based on the length of another element. So, an element that is given width: 25% in a container that is set to width: 1000px computes to width: 250px.

UnitNameRelative to…
%PercentThe size of the element’s parent container.
Font relative units

The em and rem units we looked at earlier are prime examples of relative units that you will see all over the place. They’re incredibly handy, as we saw, because changing the font-size value of an element’s parent or the <html> element, respectively, causes the element’s own font-size value to update in accordance with the updated value.

In other words, we do not need to directly change an element’s font-size when updating the font-size of other elements — it’s relative and scales with the change.

UnitNameRelative to…
emElementThe font-size value of the element’s parent container.
remRoot elementThe font-size value of the <html> element.
chCharacterThe width of the 0 character relative to the parent element’s font. The computed width may update when replacing one font with another, except for monospace fonts that are consistently sized.
rchRoot characterThe same thing as a ch unit except it is relative to the font of the root element, i.e. <html>.
lhLine heightThe line-height value of the element’s parent container.
rlhRoot element line heightThe line-height value of the <html> element.
capCapital letterThe height of a capital letter for a particular font relative to the parent element.
rcapRoot capital letterThe same measure as cap but relative to the root element, i.e. <html>.
icInternational characterThe width of a CJK character, or foreign glyph, e.g. from a Chinese font, relative to an element’s parent container.
ricRoot international characterThe same measure as ic but relative to the root element, i.e. <html>.
exX-heightThe height of the letter x of a particular font, or an equivalent for fonts that do not contain an x character, relative to the parent element.
rexRoot x-heightThe same measure as ex but relative to the root element, i.e. <html>.

Some of those terms will make more sense to typography nerds than others. The following diagram highlights the lines that correspond to relative font units.

Four lines drawn over a line of text illustrating the ascender height, x-height, baseline, and descender height.

So, at the expense of beating this concept into the ground, if width: 10ch computes to a certain number of pixels when using one font, it’s likely that the computed value will change if the font is swapped out with another one with either larger or smaller characters.

Viewport relative units
UnitNameRelative to…
vh / vwViewport Height / Viewport WidthThe height and width of the viewport (i.e., visible part of the screen), respectively.
vmin / vmaxViewport Minimum / Viewport MaximumThe lesser and greater of vh and vw, respectively.
lvh / lvwLarge Viewport Height / Large Viewport WidthThe height and width of the viewport when the device’s virtual keyboard or browser UI is out of view, leaving a larger amount of available space.
lvb / lviLarge Viewport Block / Large Viewport InlineThese are the logical equivalents of lvh and lvw, indicating the block and inline directions.
svh / svwSmall Viewport Height / Small Viewport WidthThe height and width of the viewport when the device’s virtual keyboard or browser UI is in view, making the amount of available space smaller.
svb / sviSmall Viewport Block / Small Viewport InlineThese are the logical equivalents of svh and svw, indicating the block and inline directions.
dvh / dvwDynamic Viewport Height / Dynamic Viewport WidthThe height and width of the viewport accounting for the available space changing if, say, the device’s virtual keyboard or browser UI is in view.
dvb / dviDynamic Viewport Block / Dynamic Viewport InlineThese are the logical equivalents of dvh and dvw, indicating the block and inline directions.
dvmin / dvmaxDynamic Viewport Minimum / Dynamic Viewport MaximumThe lesser and greater of dvh/dvb and dvw/dvi, respectively.

Ah, viewport units! When we say that something should be 100% wide, that means it takes up the full width of the contain it is in. That’s because a percentage unit is always relative to its nearest parent element. But a  viewport unit is always relative to the size of the viewport, or browser window. If an element has a viewport height of 100vh and a viewport width of 100vw, then it will be as tall and wide as the full browser window.

This can be a neat way to create something like a hero banner at the top of your website. For example, we can make a banner that is always one half (50vh) the height of the viewport making it prominent no matter how tall someone’s browser is. Change the CSS in the top-left corner of the following demo from height: 50vh to something else, like 75vh to see how the banner’s height responds.

There’s something else that’s very important to know when working with viewport units. You know how mobile phones, like iPhone or an Android device, have virtual keyboards where you type directly on the screen? That keyboard changes the size of the viewport. That means that whenever the keyboard opens, 100vh is no longer the full height of the screen but whatever space is leftover while the keyboard is open, and the layout could get super squished as a result.

That’s why we have the svh, lvh, and dvh units in addition to vh:

  • svh is equal to the “small” viewport height, which occurs when the keyboard is open.
  • lvh is equal to the “large” viewport height, which is when the keyboard is disabled and out of view.
  • dvh is a happy medium between svh and lvh in that it is “dynamic” and updates its value accordingly when the keyboard is displayed or not.
  • dvmin / dvmax is the greater ore lesser of dvh, respectively.

It’s a bit of a tightrope walk in some cases and a good reason why container queries and their units (which we’ll get to next) are becoming more popular. Check out Ahmed Shader’s article “New Viewport Units” for a comprehensive explanation about viewport units with detailed examples of the issues you may run into. You may also be interested in Sime Vidas’s “New CSS Viewport Units Do Not Solve The Classic Scrollbar Problem” for a better understanding of how viewport units compute values.

Container relative units
UnitNameEquivalent to…
cqwContainer query width1% of the queried container’s width
cqhContainer query height1% of the queried container’s height
cqiContainer query inline size1% of the queried container’s inline size, which is its width in a horizontal writing mode.
cqbContainer query block size1% of the queried container’s inline size, which is its height in a horizontal writing mode.
cqminContainer query minimum sizeThe value of cqi or cqb, whichever is smaller.
cqmaxContainer query maximum sizeThe value of cqi or cqb, whichever is larger.

Container units are designed to be used with container queries. Just as we are able to target a specific screen size with a media query, we can target the specific size of a particular element and apply styles using a container query.

We won’t do a big ol’ deep dive into container queries here. The relevant bit is that we have CSS length units that are relative to a container’s size. For example, if we were to define a container:

.parent-container {
  container-type: inline-size;
}

…then we’re watching that element’s inline-size — which is equivalent to width in a horizontal writing mode — and can apply styles to other elements when it reaches certain sizes.

.child-element {
  background: rebeccapurple;
  width: 100%;

  @container parent (width > 30ch) {
    .child-element {
      background: dodgeblue;
      width: 50cqi;
    }
  }
}

Try resizing the following demo. When the parent container is greater than 30ch, the child element will change backgrounds and shrink to one-half the parent container’s width, or 50cqi.


What about unit-less numbers?

Oh yeah, there are times when you’re going to see numbers in CSS that don’t have any unit at all — just a single integer or number without anything appended to it.

aspect-ratio: 2 / 1; /* Ratio */
column-count: 3; /* Specifies a number of columns */
flex-grow: 1; /* Allows the element to stretch in a flex layout */
grid-column-start: 4; /* Places the element on a specific grid line */
order: 2; /* Sets the order of elemnents in a flex or grid layout */
scale: 2; /* The elementis scaled up or down by a factor */
z-index: 100; /* Element is placed in a numbered layer for stacking */
zoom: 0.2;  /* The element zooms in or out by a factor */

This isn’t a comprehensive list of all the CSS properties that accept unit-less numeric values, but it is a solid picture of when you would use them. You’ll see that in most cases a unit-less number is an explicit detail, such as a specific column to position an element, a specific layer in a stacking context, a boolean that enables or disables a feature, or the order of elements. But note that anytime we declare “zero” as a number, we can write it with or without a prepended unit, as zero always evaluates to zero no matter what unit we’re dealing with.

border: 0; /* No border */
box-shadow: 0 0 5px #333; /* No shadow offset */
margin: 0; /* No margin */
padding: 0; /* No padding */

We can create our own custom units!

In some cases, we may want to work with a numeric value, but CSS doesn’t exactly recognize it as one. In these cases, the number is recognized as a “string” value instead, regardless of whether or not it contains alphabetical characters. That’s where we can use @property to create what’s called a “custom property” that evaluates a numeric value in a certain way.

Here’s a good example. There was a time when it was virtually impossible to animate a gradient that changes colors over time because to do so would require (1) a color function that allows us to change a color value’s hue (which we have with hsl()) and (2) being able to interpolate that hue value around the color spectrum, between a range of 0deg and 360deg.

Sounds simple enough, right? Define a variable that starts at 0 and then cycles through 360 degrees at the end of an animation. But this doesn’t work:

/* 👎 */
.element {
  --hue: 0;
  
  animation: rainbow 10s linear infinite;
  background: linear-gradient(hsl(--hue 50% 50%);
}

@keyframes rainbow {
  from { --hue: 0; }
  to { --hue: 360deg; }
}

That’s because CSS reads the variable as a string instead of a number. We have to register that variable as a custom property so that CSS aptly reads it as a numeric value.

@property --hue {
  syntax: "<number>";
  initial-value: 0;
  inherits: true;
}

There we go! Now that we’ve given CSS a hint that the --hue syntax is that of a <number>, we can animate away!

/* 👍 */
@property --hue {
  syntax: "<number>";
  initial-value: 0;
  inherits: true;
}

.element {
  --hue: 0;
  
  animation: rainbow 10s linear infinite;
  background: linear-gradient(hsl(--hue 50% 50%);
}

@keyframes rainbow {
  from { --huw: 0; }
  to { --hue: 360deg; }
}

Find a deeper explanation of this same example in “Interpolating Numeric CSS Variables” by Geoff Graham.


When to use one unit over another

This is super tricky because CSS is extremely flexible and there are no definitive or hard-and-fast rules for when to use a specific type of CSS length unit over another. In some cases, you absolutely have to use a specific unit because that’s how a certain CSS feature is specced, like using angle units to set the direction of a linear gradient:

.element {
  background: linear-gradient(
    135deg, red, blue;
  )
}

The same goes for the values we use in certain color functions, like using percentages to set the saturation and lightness levels in the hsl() function:

.element {
  background: hsl(0 100% 10%);
}

Speaking of color functions, we define alpha transparency with either an integer or number:

.element {
  background: hsl(0 100% 10% / 0.5); /* or simply .5 */
}

All that being said, many cases are going to be some degree of “it depends” but there are some instances where it makes sense to use a specific unit in your work.

Generally set font sizes in rem and em units

This way, you can set things up in a way where changing the font-size value of the <html> or a parent element updates the font sizes of their descendants.

html {
  font-size: 18px; /* Inherited by all other elements */
}

.parent {
  font-size: 1rem; /* Updates when the `html` size changes */
}

.child {
  font-size: 1em; /* Updates when the parent size changes */
}

Declare “zero” without units if you’d like

It’s not a big deal or anything, but leaving off the units shortens the code a smidge, and anytime we’re able to write shorter code it’s an opportunity for faster page performance. The impact may be negligible, but we’re able to do it since 0 always computes to 0, no matter what unit we’re working with.

Use container units for responsive design, where possible

Container queries in general are so gosh-darn great for responsive layouts because they look at the size of the container and let us apply styles to its descendants when the container is a certain size.

.parent {
  container: my-container / inline-size; /* Looks at width */
}

.child {
  display: flex;
  flex-direction: column;
  max-width: 100vh; /* 100% of the viewport */
}

/* When the container is greater than 600px wide */
@container my-container (width >= 600px) {
  .child {
    flex-direction: row;
    max-width: 50%; /* 50% of the parent elenent */
  }
}

So, if we going to size the .child element — or any of its children — it’s worth specifying sizes in relation to the container’s size with container units than, say, the viewport’s size with viewport units.

.parent {
  container: my-container / inline-size; /* Looks at width */
}

.child {
  display: flex;
  flex-direction: column;
  max-width: 100cqi; /* 100% of the container */
}

/* When the container is greater than 600px wide */
@container my-container (width >= 600px) {
  .child {
    flex-direction: row;
    max-width: 50cqi; /* 50% of the container */
  }
}

Use percentages when you’re unsure of the context

Yes, use container units for responsive design, but that only does you good if you know you are in the context of a container. It’s possible, though, that you use the same component in different places, and one of those places might not be a registered container.

In that case, go with a percentage value because percentages are relative to whatever parent element you’re in, regardless of whether or not it’s a container. This way, you can declare an element’s size as 100% to take up the full space of whatever parent element contains it.

The only word of caution is to note that we’re only basing the size on the parent. Meanwhile, container units can style any descendant in the container, no matter where it is located.

Viewport units are great for laying out containers

You may be thinking that viewport units are a bad thing since we’ve been advising against them in so many cases, like font sizing, but they are still incredibly useful, particularly when it comes to establishing a full-page layout.

I say “full-page” layout because container queries are the gold standard for sizing elements according to the space they have in their container. But if we’re working with a full page of containers, this is where viewport units can be used to establish a responsive layout at a higher level.

If the elements of individual containers look at their container for sizing information, then the sizing and placement of individual containers themselves probably ought to look at the viewport since it directly influences the amount of space on the page.

Examples

Element (em) and Relative element (rem) units

Let’s talk specifically about these two little buggers. We saw how a percentage unit calculates its size by the size of something else. em and rem units are sort of the same, but they are calculated based on the relative font size of specific elements.

Let’s start with em units and say we have an HTML element, a <div> with a .box class, and we set its font size to 20px. That means any text inside of that element is 20px.

Great, now what if we decide we need additional text in the box, and give it a relative font size of 1.5em?

See how a font size of 1.5em is larger than the 20px text? That’s because the larger text is based on the box’s font size. Behind the scenes, this is what the browser is calculating:

20px * 1.5 = 30px

So, the relative font size is multiplied by the pixel font size, which winds up being 30px.

And guess what? rem units do the exact same thing. But instead of multiplying itself by the pixel font size of the parent container, it looks at the pixel font size of the actual <html> element. By default, that is 16px.

/* This is the browser's default font size */
html {
  font-size: 16px;
}

.box {
  font-size: 1.5rem; /* 16px * 1.5 = 24px */
}

And if we change the HTML element’s font size to something else?

html {
  font-size: 18px;
}

.box {
  font-size: 1.5rem; /* 18px * 1.5 = 27px */
}
Character unit (ch)

The character unit (ch) is another is another unit relative to font size and, while it isn’t used all that often, it is amazingly great at sizing things based on the amount of content displayed in an element, because one character unit equals the width of one character of content. Here’s how I wrap my own head around it. If we have this in our HTML:

<p>The big brown dog lazily jumped over the fence.</p>

…and this CSS:

p {
  width: 10ch;
}

What we get is a paragraph that is 10 characters wide. That means the text will break after the tenth character, including spaces.

But note that the words themselves do not break. If the content is supposed to break after 10 characters, the browser will start the next line after a complete word instead of breaking the word into multiple lines, keeping everything easy to read.

If you’re wondering when you might reach for the ch unit, it’s absolutely boss at establishing line lengths that are more pleasant and legible, especially for long form content like this guide you’re reading.

Line height unit (lh)

The line-height unit (lh) looks at the line-height property value of the element’s containing (i.e., parent) element and uses that value to size things up.

.parent {
  line-height: 1.5;
}

.child {
  height: 3lh; /* 3 * 1.5 = 4.5 */
}

When would you use this? Personally, I find lh useful for setting an exact height on something based on the number of lines needed for the text. You can see this clearly demonstrated in Temani Afif’s “CSS Ribbon” effect that uses lh to establish dimensions for each row of text that makes for consistently-sized lines that adapt to whatever the parent element’s font-size value happens to be,


Absolute vs. Relative Units
Container Units
Viewport Units
Typography
Angle Units
Time Units
Resolution Units

CSS Length Units originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-length-units/feed/ 7 375815
Platform News: Rounded Outlines, GPU-Accelerated SVG Animations, How CSS Variables Are Resolved https://css-tricks.com/platform-news-rounded-outlines-gpu-accelerated-svg-animations-how-css-variables-are-resolved/ https://css-tricks.com/platform-news-rounded-outlines-gpu-accelerated-svg-animations-how-css-variables-are-resolved/#comments Fri, 02 Apr 2021 19:35:28 +0000 https://css-tricks.com/?p=337636 In the news this week, Firefox gets rounded outlines, SVG animations are now GPU-accelerated in Chrome, there are no physical units in CSS, The New York Times crossword is accessible, and CSS variables are resolved before the value is inherited.…


Platform News: Rounded Outlines, GPU-Accelerated SVG Animations, How CSS Variables Are Resolved originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
In the news this week, Firefox gets rounded outlines, SVG animations are now GPU-accelerated in Chrome, there are no physical units in CSS, The New York Times crossword is accessible, and CSS variables are resolved before the value is inherited.

Let’s jump in the news!

Rounded outlines are coming to Firefox

The idea to have the outline follow the border curve has existed ever since it became possible to create rounded borders via the border-radius property in the mid 2000s. It was suggested to Mozilla, WebKit, and Chromium over ten years ago, and it’s even been part of the CSS UI specification since 2015:

The parts of the outline are not required to be rectangular. To the extent that the outline follows the border edge, it should follow the border-radius curve.

Fast-forward to today in 2021 and outlines are still rectangles in every browser without exception:

But this is finally starting to change. In a few weeks, Firefox will become the first browser with rounded outlines that automatically follow the border shape. This will also apply to Firefox’s default focus outline on buttons.

Three sets of round yellow buttons, comparing how Chrome, Firefox, and Safari handle outlines.

Please star Chromium Issue #81556 (sign in required) to help prioritize this bug and bring rounded outlines to Chrome sooner rather than later.

SVG animations are now GPU-accelerated in Chrome

Until recently, animating an SVG element via CSS would trigger repaint on every frame (usually 60 times per second) in Chromium-based browsers. Such constant repainting can have a negative impact on the smoothness of the animation and the performance of the page itself.

The latest version of Chrome has eliminated this performance issue by enabling hardware acceleration for SVG animations. This means that SVG animations are offloaded to the GPU and no longer run on the main thread.

Side by side comparison of the Performance tab in Chrome DevTools.
In this example, the SVG circle is continuously faded in and out via a CSS animation (see code)

The switch to GPU acceleration automatically made SVG animations more performant in Chromium-based browsers (Firefox does this too), which is definitely good news for the web:

Hooray for more screen reader-accessible, progressively enhanced SVG animations and less Canvas.

There cannot be real physical units in CSS

CSS defines six physical units, including in (inches) and cm (centimeters). Every physical unit is in a fixed ratio with the pixel unit, which is the canonical unit. For example, 1in is always exactly 96px. On most modern screens, this length does not correspond to 1 real-world inch.

The FAQ page of the CSS Working Group now answers the question why there can’t be real physical units in CSS. In short, the browser cannot always determine the exact size and resolution of the display (think projectors). For websites that need accurate real-world units, the Working Group recommends per-device calibration:

Have a calibration page, where you ask the user to measure the distance between two lines that are some CSS distance apart (say, 10cm), and input the value they get. Use this to find the scaling factor necessary for that screen (CSS length divided by user-provided length).

This scaling factor can then be set to a custom property and used to compute accurate lengths in CSS:

html {
  --unit-scale: 1.428;
}

.box {
  /* 5 real-world centimeters */
  width: calc(5cm * var(--unit-scale, 1));
}

The Times crossword is accessible to screen reader users

The NYT Open team wrote about some of the improvements to the New York Times website that have made it more accessible in recent years. The website uses semantic HTML (<article>, <nav>, etc.), increased contrast on important components (e.g., login and registration), and skip-to-content links that adapt to the site’s paywall.

Furthermore, the Games team made the daily crossword puzzle accessible to keyboard and screen reader users. The crossword is implemented as a grid of SVG <rect> elements. As the user navigates through the puzzle, the current square’s aria-label attribute (accessible name) is dynamically updated to provide additional context.

Screenshot of the crossword game with an open screen reader dialog announcing what is on the screen.
The screen reader announces the clue, the number of letters in the solution, and the position of the selected square

You can play the mini crossword without an account. Try solving the puzzle with the keyboard.

CSS variables are resolved before the value is inherited

Yuan Chuan recently shared a little CSS quiz that I didn’t answer correctly because I wasn’t sure if a CSS variable (the var() function) is resolved before or after the value is inherited. I’ll try to explain how this works on the following example:

html {
  --text-color: var(--main-color, black);
}

footer {
  --main-color: brown;
}

p {
  color: var(--text-color);
}

The question: Is the color of the paragraph in the footer black or brown? There are two possibilities. Either (A) the declared values of both custom properties are inherited to the paragraph, and then the color property resolves to brown, or (B) the --text-color property resolves to black directly on the <html> element, and then this value is inherited to the paragraph and assigned to the color property.

Two CSS rulesets, one as Option A and the other as Option B, both showing how variables are inherited and resolved between elements.

The correct answer is option B (the color is black). CSS variables are resolved before the value is inherited. In this case, --text-color falls back to black because --main-color does not exist on the <html> element. This rule is specified in the CSS Variables module:

It is important to note that custom properties resolve any var() functions in their values at computed-value time, which occurs before the value is inherited.


Platform News: Rounded Outlines, GPU-Accelerated SVG Animations, How CSS Variables Are Resolved originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/platform-news-rounded-outlines-gpu-accelerated-svg-animations-how-css-variables-are-resolved/feed/ 4 337636
What does 100% mean in CSS? https://css-tricks.com/what-does-100-mean-in-css/ https://css-tricks.com/what-does-100-mean-in-css/#comments Fri, 07 Aug 2020 19:08:32 +0000 https://css-tricks.com/?p=318815 When using percentage values in CSS like this…

.element {
  margin-top: 40%;
}

…what does that % value mean here? What is it a percentage of? There’ve been so many times when I’ll be using percentages and something weird happens. …


What does 100% mean in CSS? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
When using percentage values in CSS like this…

.element {
  margin-top: 40%;
}

…what does that % value mean here? What is it a percentage of? There’ve been so many times when I’ll be using percentages and something weird happens. I typically shrug, change the value to something else and move on with my day.

But Amelia Wattenberger says no! in this remarkable deep dive into how percentages work in CSS and all the peculiar things we need to know about them. And as is par for the course at this point, any post by Amelia has a ton of wonderful demos that perfectly describe how the CSS in any given example works. And this post is no different.

To Shared LinkPermalink on CSS-Tricks


What does 100% mean in CSS? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/what-does-100-mean-in-css/feed/ 1 318815
Turning a Fixed-Size Object into a Responsive Element https://css-tricks.com/turning-a-fixed-size-object-into-a-responsive-element/ https://css-tricks.com/turning-a-fixed-size-object-into-a-responsive-element/#comments Mon, 11 May 2020 14:46:21 +0000 https://css-tricks.com/?p=308201 I was in a situation recently where I wanted to show an iPhone on a website. I wanted users to be able to interact with an application demo on this “mock” phone, so it had to be rendered in CSS, …


Turning a Fixed-Size Object into a Responsive Element originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I was in a situation recently where I wanted to show an iPhone on a website. I wanted users to be able to interact with an application demo on this “mock” phone, so it had to be rendered in CSS, not an image. I found a great library called marvelapp/devices.css. The library implemented the device I needed with pure CSS, and they looked great, but there was a problem: the devices it offered were not responsive (i.e. they couldn’t be scaled). An open issue listed a few options, but each had browser incompatibilities or other issues. I set out to modify the library to make the devices responsive.

Here is the final resizable library. Below, we’ll walk through the code involved in creating it.

The original library was written in Sass and implements the devices using elements with fixed sizing in pixels. The authors also provided a straightforward HTML example for each device, including the iPhone X we’ll be working with throughout this article. Here’s a look at the original. Note that the device it renders, while detailed, is rather large and does not change sizes.

Here’s the approach

There are three CSS tricks that I used to make the devices resizable:

  1. calc(), a CSS function that can perform calculations, even when inputs have different units
  2. --size-divisor, a CSS custom property used with the var() function
  3. @media queries separated by min-width

Let’s take a look at each of them.

calc()

The CSS calc() function allows us to change the size of the various aspects of the device. The function takes an expression as an input and returns the evaluation of the function as the output, with appropriate units. If we wanted to make the devices half of their original size, we would need to divide every pixel measurement by 2.

Before:

width: 375px;

After:

width: calc(375px / 2);

The second snippet yields a length half the size of the first snippet. Every pixel measurement in the original library will need to be wrapped in a calc() function for this to resize the whole device.

var(–size-divisor)

A CSS variable must first be declared at the beginning of the file before it can be used anywhere.

:root {
  --size-divisor: 3;
}

With that, this value is accessible throughout the stylesheet with the var() function. This will be exceedingly useful as we will want all pixel counts to be divided by the same number when resizing devices, while avoiding magic numbers and simplifying the code needed to make the devices responsive.

width: calc(375px / var(--size-divisor));

With the value defined above, this would return the original width divided by three, in pixels.

@media

To make the devices responsive, they must respond to changes in screen size. We achieve this using media queries. These queries watch the width of the screen and fire if the screen size crosses given thresholds. I chose the breakpoints based on Bootstrap’s sizes for xs, sm, and so on

There is no need to set a breakpoint at a minimum width of zero pixels; instead, the :root declaration at the beginning of the file handles these extra-small screens. These media queries must go at the end of the document and be arranged in ascending order of min-width.

@media (min-width: 576px) {
  :root {
    --size-divisor: 2;
  }
}
@media (min-width: 768px) {
  :root {
    --size-divisor: 1.5;
  }
}
@media (min-width: 992px) { 
  :root {
    --size-divisor: 1;
  }
}
@media (min-width: 1200px) { 
  :root {
    --size-divisor: .67;
  }
}

Changing the values in these queries will adjust the magnitude of resizing that the device undergoes. Note that calc() handles floats just as well as integers.

Preprocessing the preprocessor with Python

With these tools in hand, I needed a way to apply my new approach to the multi-thousand-line library. The resulting file will start with a variable declaration, include the entire library with each pixel measurement wrapped in a calc() function, and end with the above media queries.

Rather than prepare the changes by hand, I created a Python script that automatically converts all of the pixel measurements.

def scale(token):
  if token[-2:] == ';\n':
    return 'calc(' + token[:-2] + ' / var(--size-divisor));\n'
  elif token[-3:] == ');\n':
    return '(' + token[:-3] + ' / var(--size-divisor));\n'
  return 'calc(' + token + ' / var(--size-divisor))'

This function, given a string containing NNpx, returns calc(NNpx / var(--size-divisor));. Throughout the file, there are fortunately only three matches for pixels: NNpx, NNpx; and NNpx);. The rest is just string concatenation. However, these tokens have already been generated by separating each line by space characters.

def build_file(scss):
  out = ':root {\n\t--size-divisor: 3;\n}\n\n'
  for line in scss:
    tokens = line.split(' ')
    for i in range(len(tokens)):
      if 'px' in tokens[i]:
        tokens[i] = scale(tokens[i])
    out += ' '.join(tokens)
  out += "@media (min-width: 576px) {\n  \
    :root {\n\t--size-divisor: 2;\n  \
    }\n}\n\n@media (min-width: 768px) {\n \
    :root {\n\t--size-divisor: 1.5;\n  \
    }\n}\n\n@media (min-width: 992px) { \
    \n  :root {\n\t--size-divisor: 1;\n  \
    }\n}\n\n@media (min-width: 1200px) { \
    \n  :root {\n\t--size-divisor: .67;\n  }\n}"
  return out

This function, which builds the new library, begins by declaring the CSS variable. Then, it iterates through the entire old library in search of pixel measurements to scale. For each of the hundreds of tokens it finds that contain px, it scales that token. As the iteration progresses, the function preserves the original line structure by rejoining the tokens. Finally, it appends the necessary media queries and returns the entire library as a string. A bit of code to run the functions and read and write from files finishes the job.

if __name__ == '__main__':
  f = open('devices_old.scss', 'r')
  scss = f.readlines()
  f.close()
  out = build_file(scss)
  f = open('devices_new.scss', 'w')
  f.write(out)
  f.close()

This process creates a new library in Sass. To create the CSS file for final use, run:

sass devices_new.scss devices.css

This new library offers the same devices, but they are responsive! Here it is:

To read the actual output file, which is thousands of lines, check it out on GitHub.

Other approaches

While the results of this process are pretty compelling, it was a bit of work to get them. Why didn’t I take a simpler approach? Here are three more approaches with their advantages and drawbacks.

zoom

One initially promising approach would be to use zoom to scale the devices. This would uniformly scale the device and could be paired with media queries as with my solution, but would function without the troublesome calc() and variable.

This won’t work for a simple reason: zoom is a non-standard property. Among other limitations, it is not supported in Firefox.

Replace px with em

Another find-and-replace approach prescribes replacing all instances of px with em. Then, the devices shrink and grow according to font size. However, getting them small enough to fit on a mobile display may require minuscule font sizes, smaller than the minimum sizes browsers, like Chrome, enforce. This approach could also run into trouble if a visitor to your website is using assistive technology that increases font size.

This could be addressed by scaling all of the values down by a factor of 100 and then applying standard font sizes. However, that requires just as much preprocessing as this article’s approach, and I think it is more elegant to perform these calculations directly rather than manipulate font sizes.

scale()

The scale() function can change the size of entire objects. The function returns a <transform-function>, which can be given to a transform attribute in a style. Overall, this is a strong approach, but does not change the actual measurement of the CSS device. I prefer my approach, especially when working with complex UI elements rendered on the device’s “screen.”

Chris Coyier prepared an example using this approach.

In conclusion

Hundreds of calc() calls might not be the first tool I would reach for if implementing this library from scratch, but overall, this is an effective approach for making existing libraries resizable. Adding variables and media queries makes the objects responsive. Should the underlying library be updated, the Python script would be able to process these changes into a new version of our responsive library.


Turning a Fixed-Size Object into a Responsive Element originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/turning-a-fixed-size-object-into-a-responsive-element/feed/ 3 308201
`lh` and `rlh` units https://css-tricks.com/lh-and-rlh-units/ https://css-tricks.com/lh-and-rlh-units/#comments Tue, 05 May 2020 18:22:23 +0000 https://css-tricks.com/?p=308061 There’s some new units I was totally unaware of from the Level 4 spec for CSS values! The lh unit is “equal to the computed value of line-height” and rlh is the same only of the root element …


`lh` and `rlh` units originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There’s some new units I was totally unaware of from the Level 4 spec for CSS values! The lh unit is “equal to the computed value of line-height” and rlh is the same only of the root element (probably the <html> element) rather than the current element.

Why would that be useful? Šime Vidas’ has a strong point:

“Vertical Inline Centering” of an icon
.inline-icon {
  display: inline-block;
  width: 1lh;
  height: 1lh;
}

`lh` and `rlh` units originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/lh-and-rlh-units/feed/ 5 308061
Designing An Aspect Ratio Unit For CSS https://css-tricks.com/designing-an-aspect-ratio-unit-for-css/ https://css-tricks.com/designing-an-aspect-ratio-unit-for-css/#comments Wed, 13 Mar 2019 14:29:11 +0000 http://css-tricks.com/?p=284424 Rachel Andrew says that the CSS Working Group designed an aspect ratio unit at a recent meeting. The idea is to find an elegant solution to those times when we want the height of an element to be calculated in …


Designing An Aspect Ratio Unit For CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Rachel Andrew says that the CSS Working Group designed an aspect ratio unit at a recent meeting. The idea is to find an elegant solution to those times when we want the height of an element to be calculated in response to the width of the element, or vice versa.

Say, for example, we have a grid layout with a row of elements that should maintain a square (1:1) ratio. There are a few existing, but less-than-ideal ways we can go:

  • Define one explicit dimension. If we define the height of the items in the grid but use an intrinsic value on the template columns (e.g. auto-fill), then we no longer know the width of the element as the container responds to the browser viewport. The elements will grow and squish but never maintain that perfect square.
  • Define explicit dimensions. Sure, we can tell an element to be 200px wide and 200px tall, but what happens when more content is added to an item than there is space? Now we have an overflow problem.
  • Use the padding hack. The block-level (top-to-bottom) padding percentage of an element is calculated by the element’s inline width and we can use that to calculate height. But, as Rachel suggests, it’s totally un-intuitive and tough to maintain.

Chris wrote up a full rundown of possible ways to maintain aspect ratio, but none of them are as elegant as CSS Working Group’s proposed solution:

.box {
  width: 400px;
  height: auto;
  aspect-ratio: 1/1;
}

See that? An aspect-ratio property with an aspect ratio unit would calculate the height of the element based on the value of the width property.

Or, in the case of a grid layout where the columns are set to auto-fill:

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

.item {
  aspect-ratio: 1/1;
}

Very cool! But where does the proposal go from here? The aspect-ratio is included in the rough draft of the CSS Sizing 4 specification. Create an issue in the CSSWG GitHub repo if you have ideas or suggestions. Or, as Rachel suggests, comment on her Smashing Magazine post or even write up your own post and send it along. This is a great chance to add your voice to a possible new feature.

To Shared LinkPermalink on CSS-Tricks


Designing An Aspect Ratio Unit For CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/designing-an-aspect-ratio-unit-for-css/feed/ 1 284424
Gradians and Turns: the quiet heroes of CSS angles https://css-tricks.com/gradians-and-turns-the-quiet-heroes-of-css-angles/ Wed, 06 Feb 2019 15:34:36 +0000 http://css-tricks.com/?p=282291 I love coming across little overlooked CSS gems, like the gradien (grad) and turn (turn) units that Ken Bellows uncovers in his post explaining them. I don’t know, maybe y’all are already aware of them, but …


Gradians and Turns: the quiet heroes of CSS angles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I love coming across little overlooked CSS gems, like the gradien (grad) and turn (turn) units that Ken Bellows uncovers in his post explaining them. I don’t know, maybe y’all are already aware of them, but they’re certainly new to me.

They’re additional options for dealing with angles, where degrees (deg) and radians (rad) are more commonly known. I’m partial to degrees anytime I’m working with rotations. But now that I know there’s an easier way to express a half rotation by using 0.5turn instead of 180deg, I can see myself reaching for turns much more often.

When you’re designing an animation or thinking about how to add some rotation to your design, how are you thinking about it? You probably aren’t thinking in numbers. … You don’t usually think in degrees or radians. You think in terms of full turns and portions of turns. At least, I do.

After looking at his table of comparisons, I take the point:

Degrees Radians Gradians Turns My Fav Unit
30deg 0.52rad 33.33grad 0.08turn Gradians
45deg 0.79rad 50grad 0.13turn Gradians
60deg 1.04rad 66.67grad 0.17turn Gradians
90deg 1.57rad 100grad 0.25turn Turns
180deg 3.14rad 200grad 0.5turn Turns
360deg 6.28rad 400grad 1turn Turns
720deg 12.56rad 800grad 2turn Turns
1080deg 25.12rad 1200grad 3turn Turns

Hear, hear! And since these units are supported back to IE 9, seems like something fun to try out.

(Hat tip to Rachel Andrew for sharing this in her awesome CSS Layout News email.)

To Shared LinkPermalink on CSS-Tricks


Gradians and Turns: the quiet heroes of CSS angles originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
282291
The Lengths of CSS https://css-tricks.com/the-lengths-of-css/ https://css-tricks.com/the-lengths-of-css/#comments Wed, 13 Mar 2013 18:25:33 +0000 http://css-tricks.com/?p=20529 There are quite a few properties in CSS that take a length as a value. The box model properties are the obvious ones: width, height, margin, padding, border. But plenty of others as well: the …


The Lengths of CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There are quite a few properties in CSS that take a length as a value. The box model properties are the obvious ones: width, height, margin, padding, border. But plenty of others as well: the offset and sizing of a box-shadow or the size and spacing of fonts. What are all the accepted “length” properties in CSS? There are quite a few.

The Absolute Lengths

px

.wrap {
  width: 400px; 
}

Pixels don’t have anything to do with the literal screen pixels in the display you are looking at. It’s actually an angular measurement.

Nerdy bits about what pixels are in CSS

Pixels in CSS are anchored to the CSS reference pixel which is the visual angle of one pixel, 0.0213 degrees or 1.278 minutes of arc. This is based on a device with a pixel density of 96 DPI and a distance from the reader of an arm’s length of 28 inches. Device manufacturers can thus use the reference pixel to set a size based on intended/expected visual distance.

It is supposed to be a value that is normalized across devices and displays, but that increasingly isn’t true anymore. For instance, websites on the iPad mini render the same as on the iPad, meaning if those values were set in pixels that normalization is rather out the window.

Pixels are still a canonical measurement on the web though as they are consistently handled, many other lengths map directly to pixels, and JavaScript speaks in pixels.

in

.wrap {
  width: 4in; 
}

Inches are a physical measurement, but in CSS land, they just map directly to pixels. Feel free to chime in with use cases in the comments and I’ll add them here, but I have never seen a practical use case for this or the rest of these physical measurements.

1in == 96px

cm

.wrap {
  width: 20cm; 
}

For most of the world, centimeters are more familiar and useful as a physical measurement. They also just map to pixels:

1cm == 37.8px

mm

.wrap {
  width: 200mm; 
}

And an order of magnitude smaller…

1mm == 0.1cm == 3.78px

The Font-Relative Lengths

Em

.wrap {
  width: 40em; 
}

A relative unit. Originally a typographic measurement based on the current typefaces capital letter “M”. Although the length doesn’t change when you change font-family, it does change when you change the font-size.

Without any CSS at all, 1em would be:

1em == 16px == 0.17in == 12pt == 1pc == 4.2mm == 0.42cm

If any CSS changes the font size (at any level in the document), 1em becomes whatever the new font-size is.

Making things a tiny bit funkier, em units multiply upon themselves when applied to font-size, so if an element with font-size 1.1em is within an element with font-size 1.1em within yet another element with font-size 1.1em, the resulting size is 1.1 ✕ 1.1 ✕ 1.1 == 1.331rem (root em). Meaning even if an element is set to, say 10em, that doesn’t mean it will be a consistent width everywhere it appears. It could be wider or narrower if the font-size changes (see proof).

Rem

.wrap {
  width: 40rem; 
}

A relative unit, like em, but it is always relative to the “root” element (i.e. :root {}) rather than using the cascade, like em does. This vastly simplifies working with relative units.

Notable browser support issues: doesn’t work in IE 8, Safari 4, or iOS 3.2.

Points

.wrap {
  width: 120pt; 
}

A point is a physical measurement equal to 1/72 of an inch. Points are the most common way to size type outside of CSS (likely why it is supported in CSS). It’s still common in language “Of course they set this important information in tiny eight-point type!”.

Points make the most sense in print stylesheets for sizing type, where physical media is involved, but there is nothing preventing you from using pt for screen media or anywhere else a length is accepted.

Notable browser support issues: There used to be big differences in on-screen rendering of pt size. Here’s a comparison of IE 6 vs Firefox (probably 3.6).

Pica

.wrap {
  width: 12pc; 
}

The same story as points, only 1pc == 12pt.

ex

.wrap {
  width: 60ex;
}

This is a measurement based on the x-height of the current font. Sometimes that comes from information embedded in the font itself, sometimes browsers figure it out by measuring a lower case glyph, and worst case, it’s set to 0.5em. It is named “x” height because it is supposedly based on the height of the x character. To understand x-height, think of a lowercase character that as a bit that sticks up (ascender) like a lowercase “d”. The x-height doesn’t include that ascender, it is the height of the lower loop part of that character.

Unlike ems, which don’t change when you change the font-family, ex units do change when you change the font-family, as the value of one unit is specifically bound to that font. (proof).

ch

.wrap {
  width: 60ch;
}

This is similar in spirit to x-height, only ch is based on the width of the zero (0) character instead of the height of the x character. It also changes as the font-family changes.

The Viewport Percentage Lengths

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
261911166.1

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1261274.48

vw

.wrap {
  width: 10vw;
}

This is the “viewport width” unit. 1vw is equal to 1% of the width of the viewport. It is similar to percentage, except that the value remains consistent for all elements regardless of their parent elements or parent elements width. A bit like how rem units are always relative to the root.

Sizing type is the major use case here. See Viewport Sized Typography.

Notable browser support issues: No support in any mobile browsers except the very latest iOS 6. This goes for all the viewport related length units.

vh

.wrap {
  width: 10vh;
}

This is the same as the vw (viewport width) unit only it is based on the viewport height instead.

vmin

.wrap {
  width: 20vmin;
}

This value will be whichever is smaller at the moment, vw or vh. In the standard use case of sizing type, this may be a more useful metric than vw or vh on their own in determining true screen size.

vmax

.wrap {
  width: 20vmax;
}

This value will be whichever is larger at the moment, vw or vh.

Notable browser support issues: WebKit based browsers support vmin but not vmax (yet). Firefox does support vmax though.

Odd Ball Out

Percentage

.wrap {
  width: 50%; 
}

A length set in percentage is based on the length of the same property of the parent element. For example, if an element renders at 450px width, a child element with a width set to 50% will render at 225px1.

Trivia: percentage isn’t technically a length unit, but I’m including it here since it is so related.

More Information

What is supported in your browser?

See here:

Check out this Pen!

1 Assuming the child element isn’t inline-level or a table cell with some weird table-y stuff going on, or a flex child or grid cell or any other fancy wacky stuff.


The Lengths of CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-lengths-of-css/feed/ 70 20529