Making Things Better
In 2019 I presented a talk at An Event Apart about my ideas about and fears for the web platform. This post is a written version of that talk.
Redefining the technical possibilities of CSS
I have been fortunate enough to be invited to stand on the An Event Apart stage and talk about CSS for over three years now. Over that time our understanding of and abilities with CSS Layout has been totally rewritten. The An Event Apart attendees have witnessed that change, been part of the excitement.
We had been using floats as our primary layout method for over 15 years. That usage is now being resigned to history.
The happenings of the last few years being no less dramatic of the move away from tables for layout to CSS.
“Tableless web design”
If we think about tables to CSS for a moment though. That move was difficult because we asked people to limit their designs in many ways. If we look at the table layouts of early websites, some of these were incredibly complex. They were designed in graphics design applications, sliced up into pieces and reassembled in complex table structures.
A move to CSS meant a simplification, as those complex designs were not possible to create using CSS alone, we just didn’t have the tools.
A lot of the web for over a decade drew inspiration from designs such as Doug Bowman’s Minima theme for Blogger.
And this was no bad thing, I think that the move from table based designs to CSS heralded the start of us thinking about the web as it’s own medium, something which progressed with the idea of Responsive Web Design. Yes, we simplified, but we did so in order to enable great experiences for everyone.
However we downplayed the problems. Us CSS advocates, those of us involved with the Web Standards Project. We weren’t looking to see how we could improve the platform and invent new CSS to solve problems, we were campaigning for browsers and web developers alike to comply with the standards that existed, to build accessible and cross platform websites, and to be happy with our lot.
I keep coming back to this idea that what we see as good web design is rooted in the technical limitations of CSS2.
[I] accepted that CSS is just hacks over top of a document model that was never designed to be used like it is today.— Bailey Ling
I believe that the way many people see the web is still hobbled by the attitudes and limitations of those early days.
Sometimes, an audience member or a reader will object to something I demonstrate. They tell me that, “the web is not print” deeming the technique to be too close to print design. Or, I will hear the idea that CSS is something of a failed medium, without any of the things we really need, and we have to just hack at it to get what we want.
Yet times have changed.
In this article I want to show you the problems we have solved, the problems we are solving, and also point at the problems we haven’t yet solved. Because I not only want you to understand new CSS, use it, create beautiful things, and practical things, solve the problems of your site visitors in ever more elegant ways.
I also want you to be empowered to contribute to solving the new problems that we hit. I want you to know that is possible, and to walk with me to remove even more of the technical limitations of CSS.
You never know how tall anything is on the web
“We can’t control the height of things”, I would explain to the designers I was working with who would produce a design which relied on the height of things being known.
A design as simple as this one. Three boxes, different amounts of content, but we want the bottoms of those boxes to line up. Not so many years ago this was impossible, because a floated layout had no way to line up the bottom of the boxes.
So we would fix the height, based on an assumed amount of content. And, when too much content was added, and poked out the bottom of the box we would look to our CMS, see if there was a way to prevent too much content getting in.
I have a CMS product. I still get people asking how to do this for this very reason.
We hacked around the problem
Designs were created that hid the issue, a gradient that faded away and hid the fact that the boxes were uneven heights, avoiding background colors altogether, the faux columns technique of the past. A technical limitation influencing design, and even sometimes our content.
Enter flexbox and then Grid and the fact that
align-items has an initial value of
stretch and the problem not only disappeared, but the default behaviour of these layout methods was the thing we struggled with for so long.
How big is that box?
But it isn’t just about how tall the thing is, but in general how big it is. We’ve gained new abilities to size things based on how big they are. My talk in 2018 at An Event Apart is online as a video, and in that talk I unpacked some of the complexity of sizing in new layout.
And we think we know a lot about sizing because to make those floated layouts work we have to give everything a width, and make sure that the total width across the container – including margins used for gutters - doesn’t add up to more than 100%
This means that to make a responsive design, we end up using a lot of media queries to change the size at various breakpoints. For when the box gets too small for the contents suboptimal things occur, we get the CSS is Awesome problem, or the floated layout starts to fall apart.
This obsession with setting the width of things resulted in everyone believing that Flexbox should behave in the same way as floats. We find Flexbox grid systems which set the width of things exactly as we did for float-based systems. And, the fact that flex items sometimes seem to end up an unusual size is quoted in various articles as being a failure on the part of flexbox, it behaves weirdly, it isn’t intuitive.
No, it just isn’t the layout method you think it is.
If you think flexbox is for lining things up with other things then yes, it seems weird and badly behaved. Once you realise it is for taking a bunch of oddly sized things and returning the most reasonable layout for those things it makes sense.
It does this by looking at the things and seeing how big they are then assigning space to give the best sort of layout for those items, rather than squashing a big thing into a tiny column and leaving loads of spare space around a tiny thing. In doing so, it solves the problem of needing to give everything a width and then change that width when the viewport changes because it works that out for you.
It just blew my mind that someone thought the default behavior should be to just have the text honk right out of the box, instead of just making the box bigger.— Steven Frank
Staying with sizing, and the problem highlighted by the CSS is Awesome meme. What we really have here is an issue of overflow. You have made a fixed width container and are trying to put content into that container which is too big, what do you want CSS to do here?
CSS by default will do what you see in the meme because to do anything else would cause data loss, which is CSS terms means that some of your content vanishes.
We try and avoid data loss because if something on your page vanishes at certain screen sizes – because of overlap, or it going off the side of the screen, you may be unaware of it. A quick eyeballing of the page may not cause something missing to jump out at you. You will tend to spot the messy overflow though.
A good example of this design pattern can be seen in the Box Alignment specification, with the safe and unsafe alignment keywords. Safe alignment, means that your chosen alignment method won’t be used if it causes data loss, unsafe means that data loss may happen.
In certain situations, your choice of alignment method could cause overflow that results in data loss, for example by pushing an item off the side of the viewport. If you use the keyword
safe you are telling the browser that you would prefer a different alignment over data loss. The keyword
unsafe declares that you want your chosen alignment even if it causes data loss. You can see these keywords in action in a supporting browser in the CodePen below.
Overflow happens, if you fix the size of things. By default CSS tries not to cause some of your information to vanish. If you want something else to happen then you need to declare that. And you have an increasing number of options.
Better ways to stop content just “honking out of the box”
The author of the meme wondered why the box didn’t grow to fit the content. However if you give something a fixed size in CSS, it will respect that size. What the author really wanted was to make the box
min-content sized. With a box that has a width of
min-content the box will grow as big as it needs to be to contain the content, with all soft-wrapping opportunities taken, but no bigger.
If instead, you want to make the box not wrap at all, then give it a width of
max-content. The text will then display all as one line and take no soft-wrapping opportunities.
Perhaps you need to have the box that fixed width, but don’t mind if it grows taller. In that case use
Take a look at the next CodePen for all your awesome possibilities.
Being awesome vertically
A problem which perhaps many of us English speakers haven’t run into, is the fact that CSS had for any years a baked in assumption that we were all using a left to right top to bottom language. Essentially that we were all English speakers.
However CSS has also updated to match the reality that worldwide many languages are not horizontal, and running left to right, but perhaps are horizontal and running right to left, or written vertically, or maybe even a mixture of the two. The Writing Modes specification details the different writing modes and allows us to switch between them, we can do so for creative reasons or, because we are typesetting a language which uses those writing modes.
Flexbox and CSS Grid brought with them an agnostic approach to the writing mode of the document
For the first time we had to think about start and end, rather then left and right, top and bottom. This agnostic approach is apparent in alignment, and also in line-based and auto placement in grid. In fact, in my early Grid talk, which you would have seen if you came to An Event Apart sometime in late 2015 or 2016, I mentioned that if you set all four lines using the
grid-area property the order of the lines wasn’t the familiar top right bottom left of setting a margin shorthand, but instead - when in a horizontal writing - mode top left bottom right. The reverse of that order.
What that shorthand is doing is setting the block and inline start then the block and inline end, for as soon as your grid is not in horizontal-tb thinking about top, right, bottom, and left doesn’t make a lot of sense.
Logical Properties and Values
The problem then is that we have a situation where our main layout methods talk about start and end and inline and block, and everything else in CSS - floats, positioning, margins, padding and borders, all describe themselves in terms of physical dimensions.
All this specification contains is a set of mappings, and additional shorthands that give us a way of defining things in a flow relative, logical way as opposed to the physical way we are used to. If I have a grid layout with a width but then use Writing Modes to switch to a vertical writing mode, the grid layout will all work in that writing mode. However the width remains tied to the horizontal measure, meaning that the shape of the grid changes.
Instead of width I could use the new mapped property
inline-size, representing the size in the inline direction. Which for a vertical writing mode is vertical not horizontal. This would mean that once in a vertical writing mode, the
inline-size would control the height of the component and the entire grid would retain its dimensions.
Therefore if we give our awesome meme an inline-size of min-content, when we are being awesome horizontally, the inline-size runs horizontally. To be awesome vertically the inline-size runs vertically.
There are mapping like these for pretty much all properties in CSS, and some values too. I’ve recently documented these over at MDN, MDN also has lots of live examples so you can play around with the different properties.
Browser support is improving with the mapped properties, and I mention this here, partly because I think ultimately these logical, flow relative properties will become our defaults but also in the context of problem solving. In creating CSS.
An additional complexity for anything that we create in CSS is it needs to consider these writing modes. We’re not in the business of creating a better web just for horizontal language users. In fact, as I’ve looked into vertical writing more as a spec editor, I’ve realised what a wealth of interesting patterns emerge from people who use the written word in a different way to me.
There is no fold
Clients ask us to have things above the fold, and we roll our eyes as we explain for the millionth time that there is no fold on the web, that people do know how to scroll. Once responsive design became a thing, this request seemed all the more frustrating. Which fold were they talking about? The one on a watch, a phone, or a giant desktop screen?
The thing is, today we know exactly where the fold is. We can even engineer our designs to reflect on the size of the screen the user has.
Viewport units represent a portion of the height or width of the viewport. 100vw = 100% of the viewport width, so 1vw is 1% of the viewport width. 100vh is 100% of the viewport height. We can’t use percent, because that already means something in pretty much every part of CSS.
Given that we know the size of the viewport, we can create designs which make use of the viewport. The bit that the user sees. Treating that space almost as if it were a page.
My layout here is using CSS Grid Layout, and viewport units for track sizing. This means that I can size a screenful of images exactly to fit the desktop. I essentially have three pages of content, arranged using siz rows. The sizing of the rows and gap has been implemented using the
vh unit, so that I end up with
100vh. I then get a nice paged effect as I move through my gallery. If you play with the demo you will also see I’m using the CSS Scroll Snap specification to snap from screen to screen of images. In a layout like this we see the lines between the continuous media of the web and the paged media of print converging in some ways. I’ll come back that point later.
Grid and Subgrid
Before thinking more about paged media, I wanted to think a little bit about a problem that is currently being solved. I think most people would agree that CSS Grid Layout has been the biggest problem solver of the last few years, giving us a real layout system for the web for the first time. Moving us away from hacking around floated layouts to build grid-based designs.
A new problem appears however when we begin to really work with grid, we discover that one grid is not enough. I’ve got a different presentation of my gallery here, which uses grid layout and I have this time added some captions to the images. The overall layout here is a fairly straightforward grid, each individual image and caption is also a grid, by making the grid item a grid container and defining two row tracks. This enables me to stretch the image over two tracks, and place the caption in the second track.
The problem we have however is if we add additional text to the caption. It becomes taller than the other items and the effect of nice lined up boxes is diminished. We can’t line the captions up because those nested grids don’t know about each other and how big each caption is. Sound familiar?
That’s right. We never know how tall anything is on the web.
What we need is a way to ask the nested grid to use tracks defined on the parent. That way the captions could be in the same row. A change to the size of one caption would then change the height of the entire row, taking the other captions with it. This is exactly what the
subgrid value of
grid-template-rows gives us. You can see this is action in the CodePen below, as long as you use Firefox. Firefox is currently the only browser to support subgrid. If you would like to see it in Chrome, it wouldn’t hurt to go star this bug to show your support.
The point it, that as you start to design with and for these new layout methods you will hit other problems. And do you know, that’s a good thing.
Don’t fall into the trap, of becoming excited about all the new things, and when someone points out something you can’t do, perhaps scoffing, oh you think grid is so great but look, it can’t do this, feeling you need to defend it, perhaps explaining that this isn’t a limitation, the web doesn’t work like this, the web is not print, or perhaps the web is not native, or whatever ….
We just can’t do that yet
We get to do it, by finding the use cases, explaining them, writing them up. Pointing to other media and asking whether we can do that thing on the web in an elegant and performant manner. We get this stuff because we create this stuff.
Not just me, or the CSS Working Group, or the browsers, or the folk from print user agents or EPUB. All of us.
So here are my edges, the things I want to be able to do. Things I think we’re sort of close to, and where more use cases and more thinking might just help to push them over the line.
If we can back to my example of three pages of gallery images. What would happen if I wanted to put text into one of those boxes? It’s a grid layout, so the area can accept text rather than an image. However, if we end up with more content than the fixed size row will accept we get overflow. The only way to fix that is to make my track expand to auto size, and I then lose my nice paged effect because I can’t be sure that my rows will add up to 100vh. We are right back to our same problem, we don’t know how tall things are on the web. It’s like groundhog day here.
Overflow and Multicol
How might we solve this problem? We can start by taking a look at overflow in multicol. CSS Columns behave differently in a few ways depending on whether we are in Paged Media, such as a book or a printed webpage, or in Continuous Media which is what we are on the web. These things really refer to what happens with overflowing content. When you end up with more content than will fit on a page in Paged Media, a new page is created. When you end up with more content than will fit on a screen in Continuous Media you get a scrollbar and can scroll down to view more content.
In multicol on the web, if you have more content than fits on the screen the columns just get longer and longer. Eventually you have to scroll up and down to read the content, which is a terrible reading experience, and the reason people tend not to use multicol on the web.
If you fix the height of the container, to prevent the up and down scrolling thing, the overflow columns are created in the inline direction. You will end up with a horizontal scrollbar. Again, there might be some use cases for this but I don’t want to do a horizontal scrolling thing very often.
So let’s assume I’m not a maverick and want to stick with scrolling in the block dimension. What if you could say I want my multicol container to be so high - perhaps 100 viewport height high AND if there is more columns, create another 100 vh box in the block dimension and fill it with columns. Keep on doing that until you run out of columns.
How useful would that make multicol? I think that would be excellent, and this idea of overflow in the block dimension is something we are considering for a Level Two of the multicol specification.
Multicol doesn’t quite solve my problem, as even with block dimension overflow I would need space for those columns to go.
What I really want here is to be able to have some marked up content, and instead of having to work out how much can go in each box, and break it up into sections somehow, and stick some in each container, I want to let the browser deal with it.
Hey browser, this content can go into any of these boxes. Fill them up!
We already have places where CSS has come close to this idea. If we start with Paged Media. It often comes as a surprise to people how much usage there is of CSS for print and other paged media such as EPUB, when we talk about paged media we are talking about any of these things. There are user agents which turn HTML and CSS into a print ready PDF.
You need to use a specific user agent for print when you work with paged media, browsers support a very small subset of the tools that you get with a user agent such as Prince.
When creating a PDF either to use as a PDF or for print, you have the concept of a page box, which defines a physical page with a size. You can add things into the header and footer area of each page box, target left and right pages individually. You can insert content - using Generated Content - into the margin boxes of the page. Then, when you add your content, enough pages will be created to hold the content. If you add more text, increase the text size in your stylesheet, or decide to change the size of the page to make it smaller. More pages will be created – each the same.
In a paged context you can take content and flow it through as many pages as are needed to contain it. But if you think about creating web site or application with defined screens, how different is that to paged media? Perhaps not very.
Is it wrong to think of web content as a set of defined pages rather than a continuous scroll? I don’t think so, but at the moment you will fight quite a battle to make it work well. However, we have had attempts in CSS to develop a spec which would behave in the way I explained, allow the creation of sets of boxes that content could flow through. That attempt was CSS Regions.
I’m using Regions here as a demo because it helps me describe something that we can’t otherwise come close to in browsers today, and not because I expect it to end up in our browsers any time soon. As the screenshot below demonstrates, that seems unlikely. Regions was actually implemented and then removed from browsers.
The image on Can I Use above was taken before Edge moved to Chromium. Edge had an implementation of Regions and so I was able to record the following video, demonstrating how Regions worked with my grid layout.
The text is one continuous thread. It fills the boxes in turn. First filling box 1, then box 2 and moving onto fill box 3.
The problem with Regions can be understood via this example. The content flows nicely between the boxes. I get a multicol like effect between the first two boxes. The remaining content then flows into the third box.
There was no ability to do anything like the things we can do in Paged Media, no way to declare that my pages or components look like this, please create as many as you need and put the content into these boxes.
It has been suggested to me that the spec is fine because you can dump everything leftover into a final div for sad content without a home. I don’t think that is a solution anyone really wants. That’s a hack, a workaround, it feels like something not fully thought through.
Regions faltered. The code was removed from Blink. Whenever it comes up people get very tetchy. However this all really predated grid layout.
I think that now, in a world where we have Grid and where Regions makes a lot of sense, we can circle back and look at something which is like Regions again.
As with block dimension overflow for multicol, I think this is also all about overflow. Web design has always been a battle against overflow, against the fact that we never now how tall (or how big in the block dimension) anything is on the web.
The minute we decide that we have a finite page, we aren’t just scrolling forever, we have decided how big this is in the block dimension, we risk overflow and we have given ourselves the job of managing it.
Web design is mostly a batle against overflow.
Did Regions pave the way for something better?
What if, as with multicol overflow, we can say - this is my container - it’s 100vh. It looks like this, at this breakpoint, it looks like this at another breakpoint. Here is my content, I want it to flow through these boxes. If I fill all the boxes, create me another box with the same layout and continue to add content.
As with the original regions idea my content thread is a semantically marked up thing, it makes sense outside of that layout. We gain that separation of structured content and the layout. I think it would be incredibly exciting and useful. There are however things that need to be put into place before anything Regions-like can happen. CSS Regions, like multicol relies on Fragmentation, and fragmentation is not in great shape across browsers right now. And, while it is annoying enough to end up with a heading at the bottom of one column with the content in the next. It would be a dealbreaker to have the heading in a box completely disconnected from the rest of the content.
Making things better
Whether you like the idea of Regions or not, I talk about these things because this is how we get new things. This is how we solve problems.How we figure out the next big layout challenge and start to fix it. Here is another example.
At An Event Apart I ended up chatting to Rob about a problem he had with Grid. He wanted to be able to float items but still have them use the grid layout.
Because a floated item, when it becomes a grid item, loses the float behaviour he couldn’t do that. So had come up with a hacky solution to the problem and he wrote it up.
Now Rob saw this as a grid problem. He wrote it up as a grid problem.
However when I looked at it, because I’ve been digging around these specs for years, I recognised that we already had something in CSS that could solve this. The Exclusions spec – also only useable in Edge right now – solves this problem perfectly.
More importantly it gave me a great use case to take back to the CSS Working group, to show them of a real-world problem that Exclusions solved, to see if we could start talking about it and solving the problems in that spec so more browsers might implement it.
This is the sort of thing that anyone can do. Write up the things you can’t do – even guess at a solution – don’t worry if it isn’t the best solution. Figuring that out takes more than one mind most of the time – that’s why we have the CSS Working Group. But do show us. Don’t assume that because CSS doesn’t work like that now it can never work like that.
We have come so far in the last few years. The last thing I want, is for it to stop now.
Perhaps these first few years of grid, when we look back will look very grid like, as we all got excited about being able to neatly line up our boxes. That’s great, lining up boxes is a useful thing to be able to do, but let’s not allow that to define our new technical limitations, and instead keep poking at the edges and asking what next, why can’t I do that? And we’ll keep pushing at the edges, and continue to break out of the technical limitations, making things better, faster, or yes just less weird.
And this was very nearly the end of this talk. But, when I was about to present this in San Francisco for the first time something happened that I think backs up the importance I place on more people having input into the web platform.
I woke up, to the rumors that were later confirmed that Microsoft were dropping their rendering engine EdgeHTML in favour of using Chromium. And I feared that we were heading right back to the days where one browser had over 95% market share. Where one browser could quite literally dictate the direction of the web.
Many of the things I have talked about, Exclusions and Regions for example, were implemented by the Microsoft team. No, not in a perfect finished way, but enough for us to be able to experiment. Enough for us to try them out. Grid Layout was first implemented by the Microsoft Team in IE10. No, it wasnt perfect, essentially a prototype for what was to come, but it enabled people to experiment. I probably wouldn’t be known as the CSS Grid person if it hadn’t been for that implementation allowing me to start to work with the spec.
Fewer browsers mean fewer experiments. Mean fewer places where things can start to evolve. When I first gave this talk, I said I was absolutely sure that the excellent people on the Microsoft browser team, people who I would call my friends, good people, good engineers, true standards advocates would do great work on Chromium. That has already played out to be true. But ultimately, it’s a single rendering engine and is driven by the needs of Google.
And, if we are not to have diversity in rendering engines then we need to double down on making sure that there is diversity of thought involved in the standards process.
At a W3C meeting or standards discussion, the room should not be 60–70% Googlers.— Ferdy Christant
As Ferdy Christant points out, there are other players who can be involved in standards discussions, not just the people behind rendering engines. CSS Shapes, Exclusions and Regions came out of work done by Adobe.
Many of the people on the CSS Working Group represent the world of publishing. We need to make sure that those non-browser companies are given weight and impact.
We need to encourage independent voices into the process. We need to make sure that it is as easy as possible for web designers and developers to join the discussion, and encourage those who show real talent for standards work.
Then we need to make sure that every time someone comes along who is good at this, who can impact the process, who can be a different voice or represent different people, that they are supported to do so and are not just immediately hired by Google as the only route to do web platform work. A shoutout in that regard to Fronteers and their great experiment in funding me as an official representative of web developers.
And I am not having a dig at Google here, again, there are some great people doing great things there, and the company is being a company doing what companies do - growing, succeeding. This isn’t a fight between good and evil. It’s a fight against a monoculture turning the web platform into the product of a single company. Whoever that company might be this time.
So please. Participate, share your ideas, help us solve problems. And let’s work together for the future of the open web platform.