5 CSS Properties That You Probably Don’t Know

Every year new CSS properties are standardized and made available in major browsers for you to use. They are meant to make the life of web developers like you easier, and to allow the creation of new and beautiful designs.

In this article, I'll cover 5 CSS properties that are relatively new, that you've probably never heard of before and that I find very interesting. The aim of this article is to give you an overview of what they are, which values you can use, their use cases, and also some examples.

In particular, we'll cover CSS properties related to:

  • writing display (font-display and writing-mode);
  • rendering performance improvements (contain and will-change properties);
  • creation of new, fancy designs (clip-path)

Before starting, I want to remind you that, when dealing with new CSS properties, it is always a good idea to check their support and potential cross-browser issues. In that regard, Can I use is the holy grail.

1. font-display

The font-display property allows you to control how a downloadable font renders before it is fully loaded or what happens in case the download fails. How custom fonts are used and how much time it takes to load them are extremely important points to consider. Until the custom font used is loaded, in fact, users are stuck looking at blank content for a certain amount of time. And we know that, if things don't load quickly, the users leave the page. The exact time of invisible text depends on the browser used, but it's usually around 3 seconds. For the web, this period of time is quite long.

In the last few years, developers have dealt with this problem by using JavaScript-based solutions like Font Face Observer or the Font Loading API. But things can change thanks to the font-display property.

The font-display property is meant to be used in a @font-face declaration. Thanks to it, we can control how fonts display with just one simple CSS line, without the need to use the JavaScript-based solutions. This means that our web pages can lose weight and (very likely) improve performance.

If you're thinking of employing font-display, you can use one of these five values:

  • auto: The default value. This is equivalent as not using the property at all and the result is that the browser hides text that uses custom fonts that are loading. When the fonts finish loading, the text is shown.
  • block: The time that the browser hides the text while waiting for the custom font to load is reduced (for example to 1 second). As a consequence, a fallback font is displayed more promptly. However, the browser will wait indefinitely for the custom font to load and it'll always swap the latter as soon as it's available.
  • swap: The fallback text is shown immediately while the custom font loads. When the latter is ready, it's used in place of the fallback font. In most cases, this is what you might want to use and this is the behavior that the aforementioned JavaScript-based solutions have.
  • fallback: There will be a short period of time (around 100ms) that text styled with custom fonts will be invisible. The unstyled text (i.e. the text using a fallback font) will then appear if the custom font isn't ready. Once the custom font loads, the text is styled with it. However, if too much time passes, the fallback will be used for the rest of the page's lifetime.
  • optional: This value is very similar to fallback. The affected text will be invisible for a short period of time (again, around 100ms), and then the fallback font is adopted if the custom font is not ready. But with this value, the browser has the freedom to decide whether or not a font should even be downloaded and used. A reason why the browser might decide that it isn't a good choice to download the font is a user on a slow connection. You might want to employ optional for those fonts that aren't really part of the branding of the website or aren't crucial to achieve the design of the page.

An example of use of this property is shown below:

@font-face {
  font-family: AmazingFont;
  src: url('/fonts/amazingfont.woff2') format('woff2'),
       url('/fonts/amazingfont.eot') format('eot');
  font-display: fallback;
}

h1 {
  font-family: AmazingFont, Arial, sans-serif;
}

The support for this feature is still very low among browsers but things will get better very soon. Chrome 49+, Firefox 46+, and Opera 36+ all support this property behind a flag. However, Chrome 60 and Opera 47, the next release of these browsers respectively, will enable the property without the need for a flag.

In case you're wondering what will happen if you use font-display and the browser doesn't support it, the answer is that those browsers will simply ignore the property. Their behavior will be the same as the old days. If you really want to improve the experience of your users, even if the browsers don't support the property, you could fallback to one of the mentioned JavaScript-based solutions.

To read more about font-display, I suggest you to read these articles:

2. contain

If you build complex websites featuring many widgets, including third-party ones, the new contain property could be a great tool for optimizing your web pages. This property can be especially helpful if you consider the massive use of Web Components and React components in building today's web pages.

If you are looking for a way to limit the scope of the styles, layout, and paint recalculation to just one or more parts of the DOM, you can employ the contain property. If you are unfamiliar with those concepts, I suggest you to read the article 10 Ways to Minimize Reflows and Improve Performance. Another good resource, once you understand them is CSS Triggers.

Citing the W3C Specification definition of contain,

The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree.

But what does this mean in practice? It means that if you have a widget (the independent part) that, for example, has a fixed height and width in which you want to update the content and style, you can avoid the impact these changes will have on the rest of the DOM by scoping the browser's recalculation. The browser will perform less calculations, leading to better performance.

This property is quite new, thus it's not well supported. Currently, only Chrome 52+ and Opera 40+ support it. contain allows for several values, each of which lets you to limit how much rendering work the browser needs to do. Let's analyze every value in detail:

  • none: The default value. With this value no containment effects are applied.
  • size: this value turns on size containment for the element. This means that the element can be sized without the need to examine its descendants.
  • layout: this value turns on layout containment for the element. This specifies that nothing outside can affect its internal layout, and vice versa.
  • style: this value turns on style containment for the element. So, properties that can have effect on more than an element and its descendants won't affect anything outside the containing element.
  • paint: this value turns on paint containment for the element. This means that the descendants of the containing element don't display outside its boundaries. For example, if an element is off-screen (or invisible), all of its elements are off-screen (or invisible). The typical use case is an off-screen menu on mobile devices.
  • strict: the property is applied on all forms of containment and is in essence a combination of all the above values but none (that is contain: size layout style paint).
  • content: this value is like strict but without size.

An example of use of this property is shown below and it's also available as a JSFiddle. Consider the following HTML code:

<button id="button">Show menu</button>

<ul id="menu" hidden>
  <li>Home</li>
  <li>About</li>
  <li>Contact</li>
</ul>

And the following JavaScript:

const menu = document.querySelector('#menu');

document.querySelector('#button').addEventListener('click', function() {
  if (menu.hasAttribute('hidden')) {
    menu.removeAttribute('hidden');
  } else {
    menu.setAttribute('hidden', '');
  }
});

You could reduce the amount of calculations the browser does by using the contain property as follows:

#menu {
  contain: paint;
}

If you want to learn more about this property, take a look at these resources:

3. writing-mode

writing-mode isn't exactly a brand-new CSS property, but still many developers don't know about it. Admittedly, it's a property whose use cases aren't very common. The writing-mode property defines whether lines of text are laid out horizontally or vertically and the direction in which blocks progress. It is currently supported by all major browsers (including Microsoft Edge), although Internet Explorer supports different values from an earlier version of the spec. Moreover, Safari supports a vendor-prefixed version of this CSS property.

writing-mode supports the following values:

  • horizontal-tb: Content flows horizontally from left to right, vertically from top to bottom. The next horizontal line is positioned below the previous line.
  • vertical-rl: Content flows vertically from top to bottom, horizontally from right to left. The next vertical line is positioned to the left of the previous line.
  • vertical-lr: Content flows vertically from top to bottom, horizontally from left to right. The next vertical line is positioned to the right of the previous line.
  • sideways-rl: Content flows vertically from top to bottom and all the glyphs, even those in vertical scripts, are set sideways toward the right.
  • sideways-lr: Content flows vertically from top to bottom and all the glyphs, even those in vertical scripts, are set sideways toward the left.

The last two values are only supported by Firefox at the moment.

To give you an idea of how this property works, I've created a JSFiddle. The result is also shown below:

Writing mode demo

Keep in mind that the effect of some values is only clear when using languages like Japanese or Chinese. For a more comprehensive example, take a look at the demo shown in the relevant MDN page.

If you want to read a more detailed introduction to writing-mode, I suggest you the following articles:

4. clip-path

If you want to create from simple shapes to quite complex ones in CSS, the clip-path property can be handy. Using it, you can hide a specific area of an element. The most common use case is to employ the property with an image but you can be more creative than that and use clip-path with a paragraph to only show a portion of content.

The formal syntax of this property is:

clip-path: <clip-source> | [ <basic-shape> | <geometry-box> ] | none

The values have the following meaning:

  • clip-source: A URL referencing an internal or external SVG <clipPath> element
  • basic-shape: A basic shape function defined in the CSS Shapes specification
  • geometry-box: If specified in combination with a <basic-shape>, it provides the reference box for the basic shape.
  • none: No clipping is done

Each of the basic shapes has different arguments. Listing all of them is boring to read, so I'll present you with two examples to show you what you can do with this property.

A background image clipped to show only a pentagon

A background image clipped to show a custom polygon

clip-path is supported by all major browsers except both Microsoft's browsers (Edge and IE). Also, you should keep in mind some caveats for the browsers that support this property. The first is that Safari supports the property with the -webkit- prefix. The second is that all browsers that have implemented this feature have only partial support. The meaning of "partial support" varies depending on the browser. If you want to know more about it, check the relevant page on CanIUse.com. To try out clip-path, I suggest you to use Chrome, which has the best support.

To learn more about the uses of clip-path and how to add animations to this property, you can take a look at the articles listed below:

In addition, if you want a nice tool online that allows you to play with this property interactively, you can take a look at clippy.

5. will-change

We all know how speed and performance are crucial, especially on mobile devices. Their limited RAM and GPU memories make some CSS operations harder and "dangerous" to be performed (in terms of page loading speed or bad graphic impact) compared to desktop machines. What if the browser could actually know what is going to happen before it happens and, in this way, increase the responsiveness of a page?

There's a way we can give our browser some important hints and inform it ahead of time what changes on an element it should expect – using the will-change property. Thanks to this property, the browser will have the time to complete its optimization work before the action is required and the element is changed, allocating memory accordingly.

Sounds cool, right? The good news is that this property is currently supported in Chrome 53+, Opera 43+, Firefox 52+, Safari 10, and Android. (IE and Microsoft Edge don't support it). However, before continuing, there are some things you should be aware of:

  1. You should not apply this property to too many elements or if your page is performing well. It can slow down the machine and consume a lot of resources and memory, and this is not good.
  2. You should switch will-change on and off using script code before and after the change occurs.
  3. It should not be used to predict and solve potential performance problems. It has to be seen as something of a last resort after problems arise.

The will-change property can be used to avoid a hack we've been using for years: the use of translateZ() (or translate3d()) to trick the browser into pushing animations and transforms into hardware acceleration.

will-change supports four values:

  • auto: The browser will not set up any special optimizations other than the ones it normally does. This has the same effect as not specifying the property at all.
  • scroll-position indicates, as the name suggests, that you expect to change an element's scroll position any time in the near future. This value can be used to hint the browser into preparing for rendering content beyond that which is visible in the scroll window on a scrollable element.
  • contents: Specifies that the element's content is expected to change.
  • <custom-ident>: The name(s) of one or more CSS properties that you expect to change. You can insert multiple properties separated by comma. Examples of such values are transform and opacity.

If you want to know more about this property, I suggest you to read the following articles:

Conclusion

In this article I've described five new and interesting CSS properties that you might not have previously known. Have you ever used one or more of these properties? If so, what was your experience with them? And if you haven't used them, are you willing to give them a try?

Comments