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 (
table with all the internal display values and
none) since there are already so many great articles about them.
According to the CSS Display Module Level 3 spec 👇
The display property defines an element’s display type, which consists of the two basic qualities of how an element generates boxes:
👉 the inner display type, which defines the kind of formatting context it generates, dictating how its descendant boxes are laid out.
👉 the outer display type, which dictates how the principal box itself participates in flow layout.
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.
block flex instead of just
flex). This feature has already been implemented in Firefox, but other browsers don't support it yet.
Both flex and grid containers are behaving like block items by default, as both
grid 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, 👉
inline-grid display values will make them behave like inline elements, without affecting the layout of items inside the containers.
flow-root is an inner display type value, which means that it sets the inner flow of the elements. In order to properly understand
flow-root, we need to dig into something called Block Formatting Context (BFC). There is a definition in the spec, 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,
block display value, while the second one is an
inline-block element. Do you see collapsed margins in the first container? 😱
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
inline-block creates a brand new BFC.
inline-block is not the only property creating a new BFC, 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.
flow-root 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
block flow-root, whereas
inline flow-root is identical to
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
display: inline flow-root (except in Firefox). 👉 Use
display: flow-root (but check the browser support first) and
list-item 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
list-item 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
list-item creates a
::marker 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
list-item can be combined with both outer and inner display types, making really long display values (like
inline flow-root list-item).😄
Display values of
none define whether an element generates display boxes at all.
While element with
display:none will be removed from the layout together with its descendants, 👉 display value of
contents 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.
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, 👉
display:content 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
contents 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.😎
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
ruby (and corresponding
ruby-base-container display values for the internal structure)
When to use CSS
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
display: ruby property.
When to use HTML <ruby>?
In all other cases. If you have <ruby> element available, you should use it.
Authors using a language (such as HTML) that supports dedicated ruby markup 👉 should use that markup rather than styling arbitrary elements (like <span>) with ruby display values. Using the correct markup ensures that screen readers and non-CSS renderers can interpret the ruby structures.—W3C, CSS Ruby Layout Module Level 1
That is, the two aren’t mutually exclusive, but I probably won't use CSS
display: ruby 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.