Lesser-known CSS display values
Tags: css, webdev
Published: 2020-02-10 12:29:02

If you are just like me and have spent a last couple of years coding without being aware of how many CSS display values are out there, this could be a useful post for you. I will leave out the values that are most widely used (<code>block</code>, <code>inline</code>, <code>inline-block</code>, <code>flex</code>, <code>grid</code>, <code>table</code> with all the internal display values and <code>none</code>) since there are already so many great articles about them.


## Table Of Contents

👉 [What display is all about](#display)
👉 [display: inline-flex and display: inline-grid](#inline-flex)
👉 [display: flow-root](#flow-root)
👉 [display: list-item](#list-item)
👉 [display: contents](#contents)
👉 [display: ruby](#ruby)
     
    
##What display is all about <a name="display"></a>

According to the [CSS Display Module Level 3 spec](https://drafts.csswg.org/css-display/#the-display-properties) 👇
<blockquote>
The display property defines an element’s display type, which consists of the <b>two basic qualities</b> of how an element generates boxes:<br><br>

👉 <b>the inner display type</b>, which defines the kind of formatting context it generates, dictating how its descendant boxes are laid out.<br><br>

👉 <b>the outer display type</b>, which dictates how the principal box itself participates in flow layout.
</blockquote>

In other words, the inner display type describes the **behaviour of element's children**, while the outer display type defines whether the element is **block-level or inline-level**, that is, how it interacts with other, outer elements. 

Right now, display property single-value syntax feels kind of incomplete and doesn't always let you specify both inner and outer display type explicitly. Sometimes it's hard to figure out right away how the element behaves.

Luckily, the CSS Display Module Level 3 also defines new, two-value syntax for setting display values, with outer and inner display type values set separately (e.g. <code>block flex</code> instead of just <code>flex</code>). This feature has already been implemented in Firefox, but other browsers don't support it yet. 
  
## *display: inline-flex* and *display: inline-grid* <a name="inline-flex"></a>

Both flex and grid containers are behaving like **block items by default**, as both <code>flex</code> and <code>grid</code> display values are setting the outer display type to block. This means that each container will occupy the full width available, even if its corresponding HTML element is an inline item (like \<span>\). 

In case we need to modify the **outer behaviour** of the grid / flex containers, e.g. to position them side-by-side in the same row,  👉<code>inline-flex</code> and  <code>inline-grid</code> display values will make them behave like inline elements, without affecting the layout of items inside the containers.

{% codepen https://codepen.io/Ekaterina_Vu/pen/bGdbexM %}

## *display: flow-root*<a name="flow-root"></a>

<code>flow-root</code> is an **inner display type value**, which means that it sets the inner flow of the elements. In order to properly understand <code>flow-root</code>, we need to dig into something called **Block Formatting Context (BFC)**. There is a definition in the [spec](https://www.w3.org/TR/CSS2/visuren.html#normal-flow), but it's easier to explain with an example. 

There are two red \<div> elements in CodePen below, with identical children elements and formatted in the same way, except for the display value. The first container has default, <code>block</code> display value, while the second one is an <code>inline-block</code> element. Do you see **collapsed margins** in the first container? 😱

{% codepen https://codepen.io/Ekaterina_Vu/pen/ZEGzmjw %}

Top margin of the blue square and bottom margin of the paragraph are somehow ending up outside of the parent element. In the second container, we avoided margins collapsing, since it occurs only between blocks belonging to the same Block Formatting Context and 👉 display value of <code>inline-block</code> creates a brand **new BFC**.

<code>inline-block</code> is [not the only property creating a new BFC](https://developer.mozilla.org/enUS/docs/Web/Guide/CSS/Block_formatting_context), though. What if we want to keep the margins from collapsing, but also keep our container block element, remaining in his own row in layout? Among other hacks, we could do it by setting overflow to hidden, but apparently, this method may have [unwanted side effects](https://www.smashingmagazine.com/2017/12/understanding-css-layout-block-formatting-context/).

👉 <code>flow-root</code> display value is a solution to our problem as it always **generates a block container box and establishes a new BFC** for its content. As an inner display type, it is actually short for <code>block flow-root</code>, whereas <code>inline flow-root</code> is identical to <code>inline-block</code> value. 

Now we can use display values to **create new BFC on both block and inline elements**, which can be useful not only when handling margins, but for example, when we need to contain floats without using the clearfix hack.

 Rememeber, the two-value syntax is not quite alive yet, so you can't use <code>display: inline flow-root</code> (except in Firefox). 👉 Use <code>display: flow-root</code> (but check the [browser support first](https://caniuse.com/#feat=flow-root)) and <code>display:inline-block</code> instead.

## *display: list-item* <a name="list-item"></a>

<code>list-item</code> is the **default display value for \<li> element**. It generates a block box for the content and a separate inline box for the marker. In Firefox, the \<summary> element also has <code>list-item</code> default display value, but only if it is the first child of the \<details> element. 

You can specify image, position and type for the list marker, but not distinct styles (like colors or fonts). However, in Firefox <code>list-item</code> creates a <code>::marker</code> pseudoelement, which has a wider set of allowable properties.

Yes, I use this one quite a lot, but most of the time I wasn't aware that list items use this special display value. Why does it even matter? Well, in the two-value syntax <code>list-item</code> can be combined with both outer and inner display types, making really long display values (like <code>inline flow-root list-item</code>).😄

## *display: contents* <a name="contents"></a>

Display values of <code>contents</code> and <code>none</code> define **whether an element generates display boxes at all**.

While element with <code>display:none</code> will be removed from the layout together with its descendants, 👉 display value of <code>contents</code> **removes only the element from the document tree and its children are replacing it**. Use it with care as it is marked as an experimental feature on MDN 🧪, although with [fairly good browser support](https://caniuse.com/#feat=css-display-contents).

It makes it especially beneficial to use **with Grid or Flexbox**, since only the direct descendants of grid or flex containers are behaving as flex /grid items. In case we need to go down one level and make 'the grandchildren' behave as flex / grid items of the main container, 👉 <code>display:content</code> on the direct child of the main container will prevent it from generating a box, and its children will take its place.

In the example below, both purple rectangles are grid containers with orange rectangles as children and grid items. Yellow rectangles are children of the first orange rectangle. In the second container,👉 first orange rectangle is given display value of <code>contents</code> and is no longer visible. His children (yellow rectangles) are taking his place as grid-items, acting as if they were direct descendants of purple rectangle.😎

{% codepen https://codepen.io/Ekaterina_Vu/pen/BaNBvXe %}


## *display: ruby* <a name="ruby"></a>

Ruby annotations are used for adding explanation or pronunciation to base text (usually to East Asian characters). There are two ways of adding a ruby annotation:

 👉 with HTML \<ruby> element (and corresponding \<rt>, \<rb>, \<rtc> and \<rbc> elements for the internal structure)
 👉 with CSS display value of <code>ruby</code> (and corresponding <code>ruby-text</code>, <code>ruby-base</code>,<code>ruby-text-container</code> and <code>ruby-base-container</code> display values for the internal structure)

**When to use CSS <code>display: ruby</code>?**

For document languages (such as XML) that **do not have pre-defined ruby elements **like HTML does, corresponding elements can be translated to ruby elements with the CSS <code>display: ruby</code> property.

**When to use HTML \<ruby>?**

In all other cases. If you have \<ruby> element available, you should use it.

<blockquote><p>Authors using a language (such as HTML) that supports dedicated ruby markup 👉 should use that markup rather than styling arbitrary elements (like &lt;span&gt;) with ruby display values. Using the correct markup ensures that screen readers and non-CSS renderers can interpret the ruby structures.</p>
<footer>—W3C, <cite><a href='https://drafts.csswg.org/css-ruby-1/#intro'>CSS Ruby Layout Module Level 1</a></cite></footer>
</blockquote>

That is, **the two aren’t mutually exclusive**, but I probably won't use CSS <code>display: ruby</code> very often. I tried them both in Firefox and found some subtle differences in default behaviour, which indicates there is still room to further investigate this matter.🤯 

It seems like HTML \<ruby> alone is good enough for a simple ruby structure, along with some optional ruby-related CSS properties to fine tune the positioning of the ruby text.