CSS News July 2020
CSS News July 2020
Rachel Andrew
Things move a lot faster than they used to in terms of the implementation of Web Platform features, and this post is a round-up of news about CSS features that are making their way into the platform. If you are the sort of person who doesn’t like reading about things if you can’t use them now, then this article probably isn’t for you — we have many others for you to enjoy instead! However, if you like to know what is on the way and read more about the things you can play with in a beta version of a browser, read on!
Flexbox Gaps
Let’s start with something that is implemented in the shipping version of one browser, and in beta in another. In CSS Grid, we can use the gap
, column-gap
and row-gap
properties to define the gaps between rows and columns or both at the same time. The column-gap
feature also appears in the Multi-column layout to create gaps between columns.
While you can use margins to space out grid items, the nice thing about the gap
feature is that you only get gaps between your items; you do not end up with additional space to account for at the start and end of the grid. Adding margins has typically been how we have created space between flex items. To create a regular space between flex items, we use a margin. If we do not want a margin at the start and end, we have to use a negative margin on the container to remove it.
It would be really nice to have that gap feature in Flexbox as well, wouldn’t it? The good news is that we do have — it’s already implemented in Firefox and is in the Beta version of Chrome.
In the next CodePen, you can see all three options. The first are flex items using margins on each side. This creates a gap at the start and end of the flex container. The second uses a negative margin on the flex container to pull that margin outside of the border. The third dispenses with margins altogether and instead uses gap: 20px
, creating a gap between items but not on the start and end edge.
Mind The Gap
The Flexbox gap
implementation highlights a few interesting things. Firstly, you may well remember that when the gap feature was first introduced to Grid Layout, the properties were:
grid-gap
grid-row-gap
grid-column-gap
These properties were shipped when grid first appeared in browsers. However, in much the same way as the alignment features (justify-content
, align-content
, align-items
, and so on) first appeared in Flexbox and then became available to Grid (once it was decided the gap features were useful to more than grid), they were moved and renamed.
Along with those alignment features, the gap properties are now in the Box Alignment specification. The specification deals with alignment and space distribution so is a natural home for them. To prevent us from having multiple properties prefixed with a spec name, they were also renamed to drop the grid-
prefix.
If you have the grid-
prefixed versions in your code, you don’t need to worry. They have been kept as an alias of the properties so your code won’t break. For new projects, however, the unprefixed versions are implemented in all browsers.
Detecting Gap Support For Flexbox
You might be thinking that you could use the gap feature in Flexbox and use Feature Queries to test for support by using a margin as fallback. Sadly, this isn’t the case because feature queries test for a name and value. For example, if I want to test for grid support, I can use the following query:
@supports (display: grid) { .grid { /* grid layout code here */ } }
If I were to test for gap: 20px
, however, I would get a positive response in Chrome which currently does not support gap in Flexbox but does support it in Grid. All those feature queries do is check to see if the browser recognizes the property and value. They have no way to test for support within a particular layout mode. I raised this as an issue in the CSS WG, however, it turns out to not be an easy thing to fix, and there are limited places currently where we have this partial implementation problem.
Aspect Ratio Unit
Some things have an aspect ratio that we want to preserve, and image or a video for example. If you place an image or video directly on the page using the HTML img
or video
element, then it nicely keeps the aspect ratio it arrives with (unless you forcibly change the width or height). However, we sometimes want to add an element with no intrinsic aspect ratio while making one dimension flexible with the other retaining a specific aspect ratio. This most often happens when we embed a video with an iframe, however, you might also want to make perfectly square areas on your grid (something which also requires that one dimension can react to another).
The way we currently deal with this is by way of the padding hack. This uses the fact that padding in the block direction is copied from the inline direction when we use a percentage. It’s a not very elegant solution to the problem, but it works.
The aspect ratio unit seeks to solve that by allowing us to specify an aspect ratio for a length. Chrome has implemented this in Canary, so you can take a look at the demo below using Canary if you enable the Experimental Web Platform Features flag.
I have created a grid layout and set my grid items to use a 1 / 1
aspect ratio. The width of the items is determined by their grid column track size (as is flexible). The height is then being copied from that to make a square. Just for fun, I then rotated the items.
In Canary, you can take a look in the demo and see how the items remain square even as their track grows and shrinks, due to the fact that the block size is using a 1/1
ratio of the inline size.
Native Masonry Support
Developers often ask if CSS Grid can be used to create a Masonry- or Pinterest-styled layout. While some demos look a bit like that, Grid was never designed to do Masonry.
To explain, you need to know what a Masonry layout is. In a typical Masonry layout, items display by row. Once the first row is filled, new items populate another row. However, if some of the items in the first row are shorter than others, the second-row items will rise up to fill the gap. The Masonry library is how many people achieve this using JavaScript.
If you try to create this layout using CSS Grid and auto-placement, you will see that you lose that block direction rearrangement of items. They lay themselves out in strict rows and columns because that is what a grid does.
So could grid ever be used as a Masonry layout? One of the engineers at Mozilla thinks so, and has created a prototype of the functionality. You can test it out by using Firefox Nightly with the flag layout.css.grid-template-masonry-value.enabled set to true
by going to about:config
in the Firefox Nightly URL bar.
While this is very exciting for anyone who has had to create this kind of layout using JavaScript, a number of us do wonder if the grid specification is the place to define this very specific layout. You can read some of my thoughts in my article “Does Masonry Belong In The CSS Grid Specification?”.
Subgrid
We have had support for the subgrid
value of grid-template-columns
and grid-template-rows
in Firefox for some time. Using this value means that you can inherit the size and number of tracks from a parent grid down through child grids. Essentially, as long as a grid item has display: grid
, it can inherit the tracks that it covers rather than creating new column or row tracks.
The feature can be tested in Firefox, and I have lots of examples that you can test out. The article “Digging Into The Display Property: Grids All The Way Down” explains how subgrid differs from nested grids, and “CSS Grid Level 2: Here Comes Subgrid” introduces the specification. I also have a set of broken-down examples at “Grid by Example”.
However, the first question people have when I talk about subgrid is, “When will it be available in Chrome?” I still can’t give you a when, but some good news is on the horizon. On June 18th in a Chromium blog post, it was announced that the Microsoft Edge team (now working on Chromium) are working to reimplement Grid Layout into the LayoutNG engine, i.e. Chromium’s next-generation layout engine. Part of this work will involve also added subgrid support.
Adding features to browsers isn’t a quick process, however, the Microsoft team brought us Grid Layout in the first place — along with the early prefixed implementation that shipped in IE10. So this is great news and I look forward to being able to test the implementation when it ships in Beta.
prefers-reduced-data
Not yet implemented in any browser — but with a bug listed for Chrome with recent activity— is the prefers_reduced_data
media feature. This will allow CSS to check if the visitor has enabled data saving in their device and adjust the website accordingly. You might, for example, choose to avoid loading large images.
@media (prefers-reduced-data: reduce) { .image { background-image: url("images/placeholder.jpg"); } }
The prefers_reduced_data
media feature works in the same way as some of the already implemented user preference media features in the Level 5 Media Queries Specification. For example, the media features prefers_reduced_motion
and prefers_color_scheme
allow you to test to see if the visitor has requested to reduce motion or a dark mode in their operating system and tailor your CSS to suit.
::marker
The ::marker
pseudo-element allows us to target the list marker. At a very straightforward level, this means that we can target the list bullet and change its color or size. (This was previously impossible due to the fact that you could only target the entire list item — text and marker.)
Support for ::marker
is already available in Firefox, and can now be found in Chrome Beta, too.
In addition to styling bullets on actual lists, you can use ::marker
on other elements. In the example below, I have a heading which has been given display: list-item
and therefore has a marker which I have replaced with an emoji.
Note: You can read more about ::marker
and other list-related things in my article “CSS Lists, Markers and Counters” here on Smashing Magazine.
Please Test New Features
While it’s fun to have a little peek into what is coming up, I recommend testing out the implementations if you have a use case for any of these things. You may well find a bug or something that doesn’t work as you expect. Browser vendors and the CSS Working Group would love to know. If you think you have found a bug in a browser — perhaps you are testing ::marker
in Chrome and find it displays differently to the implementation in Firefox — then raise an issue with the browser: “How To File A Good Bug” explains how. If you think that the specification could do something it doesn’t yet, then raise an issue against the specification over at the CSS Working Group GitHub repository.
Articles on Smashing Magazine — For Web Designers And Developers