CSS units and variables
In this kata, we’re going to answer the following questions:(link to the complete list of questions)
One last step before learning new CSS properties: we must learn about various CSS units that we can use as values of those properties. Like selectors, there are a lot of CSS units, but we’ll list only the most useful ones.
Let’s start with colors. You can define a color by:
- Using a keyword (red, blue, lightgoldenrodyellow...). Link to the complete list of color keywords
- Using a hexadecimal code (#02798b, #c55da1...). This is probably the most common way colors will be defined on various websites
- Using a RGB/RGBA value (rgb(2, 121, 139), rgba(18, 138, 125, .9)...). The Alpha channel of RGBA colors controls opacity, but remember that it is different from the opacity property, which sets the opacity of the whole element
Alright, quite simple. But a lot more can be said about length units. We can split them into two categories: absolute units and relative units.
Absolute units are generally considered to always appear the same size. The ones you’ll use and see:
- The classic CSS unit. The exact definition in the CSS specification is that it should measure 1/96th of an inch. However, in practice a CSS px never maps exactly to 1/96th of an inch nor a device pixel, and you shouldn’t assume it will. This is because depending on user’s zoom setting, the screen’s physical size and actual resolution, the CSS px will be a reference unit adapted for optimal usage. For instance, on a high pixel density Retina display the CSS px unit might be represented by multiple device pixels, mapping the CSS px close to 1/96th of an inch. Why is this important? Depending on the zoom setting and how the browser handles fractions of a pixel, a 1px thick line will look differently and might even disappear. Understanding that will help you understand some "bugs" and visual glitches.
- cm and mm
- If you ever have to design something for print, these will be useful.
Relative units are always relative to something else:
- Depending on the property, represents a percentage of a property of the parent element.
- A percentage of the font-size of the element itself. If the current element has a computed font-size of 20 pixels, 1.25em will represent 25 pixels
- A percentage of the font-size of the root <html> element
- vh, vw
- A percentage of the viewport height and width. For instance, 50vh represents half the height of the browser window current height
- The width of the glyph 0 of the element’s font. Might be useful in some very specific cases (for instance wanting a width of exactly 8 characters)
Task: set the boxes to use the correct units!
Which unit should I use? Always go with the designer’s intent. Most of the time, the designer’s intent will be clear in the mockups. If it is not the case, go talk to her/him. CSS should always be the closest description of the designer’s intent.
However, pixels are an exception. You should never use px for font-size: some users and devices prefer to set a custom font-size for better readability and accessibility. If you set a font-size value with px, you are saying to those users: "I don’t care about you". Prefer rem and em that scale with the base font size.
Then, if font-size are set with rem and em, you probably want your spacing properties (padding, margin...) to use these values too. Otherwise the layout would not scale the same way as your font size, leading to unexpected visual bugs. As a bonus, if you ever want to change the base font size of your website, everything will scale automatically.
But most designers use pixels! Yes, but as we care about our users and the vast tapestry of possible devices they use, we should use rem and em. Fear not! As we’ll see with preprocessors and CSS-in-JS, there are easy ways to convert pixels to these units. Here is an excellent article explaining the px vs em issue.
When handling CSS values there are many pitfall that you want to avoid. The first of them is hardcoding values that may change.
Usually when we develop we use variables to describe values that may change and it is a good practice to never hardcode "constants". CSS is no exception. Imagine if you want to change the whole color scheme of your website. You would have to go through all your CSS files!
Hopefully, CSS does have variables and you can use variables if you don’t have to support IE 11. You can define a variable in a global scope or a local one and use them with the var() function. Try it for yourself!
Task: make the disclaimer more important by turning it red using a variable
Furthermore, you can also use the calc() function to compute length from different length units. For instance, calc(50% + (var(--header-height) / 2)) is totally possible!
If I have to support IE 11? In the "Advanced CSS", we’ll see preprocessors and CSS in JS, which have great solutions to this problem (and many others). Just be patient!
When should I use variables? Almost everywhere! In addition to be easier to change, variables also convey sense because the values are named. Take the two versions of this code that does the same thing (don’t worry about the box-sizing and overflow properties, we’ll see them soon):
Yes, the second version is longer than the first version. And yes, the second version is more maintainable and less prone to bugs than the first version.
The Cascade and special values🔗
As you may have guessed, some properties will cascade their value to children elements. After all, we’re writing Cascading Style Sheets. This is the case with the color property: when changing the color of an element, it will apply to all children if not overriden. Other properties are non-cascading: this is the case with border for instance. There are 3 special values that enable you to control the cascade:
- Forces the cascade: if the parent element defines the property, it will take the same value.
- Stops the cascade: tells the element to use the initial value defined by the browser styles, irrelevant of if the parent defines a value for this property.
- Resets the cascade to the expected behavior: behaves as inherit for cascading properties and initial for non-cascading properties.
Task: change the footer link style so that it takes the footer’s color and do not shows a border on hover
What I should remember🔗
- CSS px are not device pixels nor the same size across devices.
- Always go with the designer’s intent when choosing units.
- Except for pixels, you should prefer rem and em units for font sizes and spacing.
- Use variables and calc() to make your code easier to read, change and maintain
- inherit forces the cascade, initial stops it and unset resets it.