Utilizing the “C in CSS
Azin Asili
Posted on February 8, 2017
This article was originally posted on the Graphite GTC blog.
For a lot of developers CSS is a tricky beast to handle. Developers always tack on rules to the end of their styles sheets, causing some unintended consequences. After some raging and cursing at why CSS exists, an !important
is added and voilà , it all works. Most of the time, these issues are caused by the cascading nature of CSS. Because of the deep seeded hatred for the “C in CSS, many smart people developed methodologies to help reduce this feature or to completely remove it. These methodologies include OOCSS, SMACSS, and, BEM.
The point of this post is not to argue against these methodologies; they’re really useful in managing your style sheets and also to keep your CSS uniform. What if we were able to use the cascading feature of CSS to our benefit? Imagine if we could write one CSS rule and have it propagate to the descending elements.
To truly utilize the cascading nature of style sheets we will need to use some lesser known CSS units and keywords. We will employ the following:
- EM (and sometimes REM) units
- inherit
- currentColor
EMs and REMs
You’re probably familiar with using PX
units for sizing elements, margin, padding, borders, etc. We can do the same with EMs
and REMs
but with the added benefit that these units are relative rather than absolute values. MDN defines EMs
as:
This unit represents the calculated font-size of the element. If used on the font-size property itself, it represents the inherited font-size of the element.
MDN also gives this tidbit about EMs
This unit is often used to create scalable layouts, which keep the vertical rhythm of the page, even when the user changes the size of the fonts. The CSS properties line-height, font-size, margin-bottom and margin-top often have values expressed in em.
Note that MDN says that EMs
“represents the inherited font-size of the element” and are “used to create scalable layouts”. This is the exact thing we are looking for! Here is what MDN says about REMs
:
This unit represents the font-size of the root element (e.g. the font-size of the element). When used on the font-size on this root element, it represents its initial value.
The biggest difference between the two is REMs
always references it’s value based on the root element’s font-size
, while EMs
inherits it’s unit from the element’s font-size
. If this seems confusing, don’t worry, take a look at the following CSS to get a better understanding:
.element {
font-size: 20px;
padding: .5em;
}
In the example above the element’s padding would equate to 10px. Remember EM
units are relative to the element’s font-size
, this means our padding equation is 20 * .5 = 10.
.element {
font-size: 20px;
padding: .5em;
}
.element-child {
font-size: .25em;
padding: 1em;
}
Imagine this scenario: we know that .element
padding is equal to 10px, but what about the values for .element-child
? Well because EMs
compound our math, things can get a little tricky. The font-size
for .element-child
will equate to 5px (20 * .25 = 5). Since the parent element has a font-size
of 20px and we defined the child element as .25em of the parent’s, our compounded value is equal to 5px. The padding is a lot easier in this case, because EMs
look at the font-size
value, our padding equates to 5px.
Hopefully that wasn’t too much to handle. The tricky part with EMs
is managing how to calculate the output values. Since it’s a hassle I’ve created a set of functions and mixins for Sass to make our lives easier! You can find the Github Gist here.
Inherit Keyword
Another tool in our arsenal is the inherit
keyword, this value allows us to get the style that is defined on a parent element and apply it to the child. We can do this without having the same rule defined twice. MDN defines inherit
as the following:
The inherit CSS-value causes the element for which it is specified to take the computed value of the property from its parent element. It is allowed on every CSS property.
Imagine the following scenario using the inherit
keyword:
.element {
background: coral;
padding: 1em;
}
.element-child {
color: white;
padding: inherit;
}
Our .element-child
would get the value for padding from .element
and apply it to itself. This is nice because if the padding
on .element
changes, so will the padding
for .element-child
! This is perfect if we are trying to avoid writing the same styles multiple times. The one downside of this technique is the keyword only looks at the parent elements value; we are unable to move up in the DOM tree and get the value of an ancestor element.
CurrentColor Keyword
This keyword acts like inherit
with one big difference, currentColor
can be used to inherit the color of properties that normally do not inherit that value. MDN defines currentColor
as the following:
The currentColor keyword represents the calculated value of the element's color property. It allows to make the color properties inherited by properties or child's element properties that do not inherit it by default.
Now that we have some knowledge of the techniques we can use to manage how our values cascade, let’s put it into action.
Examples of our new techniques
See the Pen Utilizing the 'C' in CSS - Button Example by Azin Asili (@azinasili) on CodePen.
The above example is just getting our feet wet. Although it’s simple, it perfectly shows how EMs
can be used to scale our elements. You will notice two buttons, both look the same except .btn--large
is, well larger. Even though the button is larger, we never adjusted the padding for the button or even reset it’s border-radius
, instead we only adjusted the font-size
. Neat!
Because EMs
inherit the font-size
value, any property that is also using EMs
will scale. Since our .btn--large
is 1.25x larger than the initial .btn
, that means the other values will also be 1.25x larger. This is exactly what we want with our cascade. The compounding of values may cause issues if you’re not careful, but when deliberately used it can be the best way to create alternative sized elements with minimum effort.
See the Pen Utilizing the 'C' in CSS - Cards by Azin Asili (@azinasili) on CodePen.
This card example expands on some of the principals for cascading. Again, we are using EMs
to size our elements but now we are also using the currentColor
and inherit
keywords to style certain elements. Rather than hard-coding colors and other values, we can use our handy keywords to have the styles cascade down to the element we want.
See the Pen Utilizing the 'C' in CSS - Pricing Table by Azin Asili (@azinasili) on CodePen.
Our last example will demonstrate our new found cascading knowledge and apply it to a more real-world scenario. Much like the other examples we will continue to use EMs
to size our elements, but with one exception, the margin
on .price
will use REMs
instead. This is because we do not want our margins to scale with any changes to font-size
. Notice the middle table is larger than the other two? We not only use color to highlight that specific option but we also resized the whole table to be larger than the other two. Both the color and the increase in size is to draw attention to our customers. Normally with the larger sized element we would have to resize every padding
and font-size
properties. Instead we use the power of EM
and the cascade to do this for us.
Final Thoughts
The above techniques are a fantastic way to take back control of your CSS, however, it does take a little extra brainpower. Using EMs
for unit values can cause issues when you have nested elements. This can be solved with some simple math or with functions/mixins if you’re using Sass or any other pre/post processor. Either way, a little bit of extra effort can go a long way, making your style sheets more flexible and scalable for your projects. Let me know what you guys think!
Posted on February 8, 2017
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.