Skip to main content

Tagged “cssgrid”

Use z-index only when necessary

There’s a great section on Source order and layers in Every Layout’s Imposter layout. It’s a reminder that when needing to layer one element on top of the other you should:

  1. favour a modern layout approach such as CSS Grid over absolute positioning; and
  2. not apply z-index unless it’s necessary.

which elements appear over which is, by default, a question of source order. That is: if two elements share the same space, the one that appears above the other will be the one that comes last in the source.

z-index is only necessary where you want to layer positioned elements irrespective of their source order. It’s another kind of override, and should be avoided wherever possible.

An arms race of escalating z-index values is often cited as one of those irritating but necessary things you have to deal with using CSS. I rarely have z-index problems, because I rarely use positioning, and I’m mindful of source order when I do.

Layering elements with Grid rather than positioning

A while back I bookmarked Michelle Barker’s CSS Grid based overlay technique which neatly allows layering one element atop another using CSS Grid rather than absolute positioning. Now, Stephanie Eckles has taken the idea a step further with her Smol Stack Layout which offers a more flexible markup structure, some intuitive grid area naming and a neat aspect-ratio API.

Stephanie’s component is feature-packed and opinionated to the extent that it took me a while to understand all the moving parts. So for simplicity I’ve created a pared-back version on CodePen: see Layering utility with CSS Grid.

While Michelle’s utility kept the markup really simple with the container doubling-up as the first visual “layer in the cake”, I think for flexibility and robustness I prefer Stephanie’s approach where the container only serves to set the aspect ratio, with the layers represented by two or more child elements.

Layering text upon images

In Smol background picture, Stephanie goes further, leaning on her layering utility to cleverly layer text upon images. This is a modern alternative to the type of effect we previously achieved with background images. It uses a content image marked up using <picture> to progressively enhance the format (heavier-weight jpg for old browsers, lightweight webp for new browsers) and is styled with object-fit: cover in order to perfectly span its container.

This modern approach is great because often from an accessibility perspective our background images should really be content, described properly with alt, to provide equivalent visual and non-visual experiences. Furthermore using a content image tends to be better for performance with there now being so many new image techniques and attributes at our disposal when compared to background images. Lastly, handling the image as content makes it more flexible for styling.

Using Grid for a “Hero” Banner

Another noteworthy member of this family of techniques from Stephanie is her Hero with CSS Grid. Here she uses the same idea of a single grid-template-area with child content and image stacked up in layers, alongside some nifty use of grid positioning properties to align elements within that. This one is very flexible, very responsive, and super-useful.

Summing up

I really like this move away from absolute positioning because it always felt brittle. It doesn’t play well with responsive layouts, and isn’t resilient to cases where adjacent elements could overlap. Furthermore you often see absolute positioning used in conjunction with pseudo elements and while I’ve occasionally taken this approach (and appreciate the creativity behind these techniques) I’ll admit I find it much easier to read and maintain CSS that relates to actual structural elements rather than “magical” CSS elements. I much prefer these simple, modern and fit-for-purpose CSS Grid based approaches.

Changing visual order with CSS

When considering using Flexbox or CSS Grid to change the visual order of elements, remember that “with great power comes great responsibility”.

Flexbox and CSS Grid have given us new powers to shuffle the visual order of elements on a web page such that it is different to the element order in the source code.

However many smart developers have rightly pointed out that although this is really convenient and can help in conquering gnarly design and responsive challenges, it’s often not a good idea. Rachel Andrew in particular has regularly offered the following advice:

Don’t fix source problems with Grid or Flexbox.

See Rachel’s talk Grid, content re-ordering and accessibility for more detail.

So, what’s the problem?

Essentially we cause people problems when we create a disconnect between tabbing order and visual order.

Let’s dig into the detail.

People browse web pages in different ways

We know that a web page’s visitors are likely to have a range of different abilities. While some experience the full extent of our visual design, others are visually-impaired or blind. Others still have motor impairments. The web was intended to be accessible and therefore web pages should cater appropriately to this range of user needs.

Relatedly we also know that people will use one or more of the following methods to move around a web page:

  • a thumb and fingers;
  • a mouse (or trackpad) and keyboard;
  • a keyboard alone.

There are probably other methods I’m forgetting, but those are the most common.

In order to cater to people who navigate a web page using a keyboard without a mouse (a.k.a. keyboard users), we must ensure that the page is tab-friendly. We want the page’s interactive elements to be navigable and focusable by pressing the Tab key. Those elements should be focusable one by one in the same order as they are defined in the HTML document.

Often, achieving tab-friendliness requires little or no additional development effort because the browser gives us so much of the necessary behaviour natively. Interactive HTML elements like anchors (links) and form controls are focusable by default. And for any custom interactions where we want to make a normally non-focusable element (such as a div) focusable (thus giving it a keyboard tab-stop) we can apply the tabindex attribute, setting its tabindex="0".

A simple, well-formed web page will natively offer a natural and predictable tabbing order.

With CSS Grid and Flexbox we now have new CSS options such as order, flex-direction: row-reverse and grid-auto-flow which let us reorder elements on the page. This can be really handy for situations where a design spec calls for Element 1 to appear above Element 2 on narrow viewports but to its right on wider viewports. Using these new CSS properties we might let the elements follow the source order on narrow viewports but change their order within a media query for wider viewports.

However this means we are now messing with the natural order of things. And if we move focusable elements around such that their visual order is different from their source order this creates a disconnect between tabbing order and visual order.

The disconnect is unlikely to be apparent to sighted people on a tablet/phone or on a desktop setup and navigating with their mouse, because they are not using tab to navigate. Blind users using a screen reader will be similarly unaffected because they don’t experience the visual order.

We might assume that all keyboard (only) users are also blind, using a screen reader, and not perceiving visual order. However keyboard users also include sighted people who have trouble operating a pointing device such as a mouse or trackball, or whose mouse is currently not working, or who simply prefer to use a keyboard where possible.

For the sighted person who navigates by keyboard our change of order would be confusing. When you use tab and expect that to follow convention and set focus on one element but it actually sets focus on another, you’ll likely assume that something is broken.

Rachel Andrew argues that creating this kind of disconnect is to be avoided. Léonie Watson suggests that in simple examples such a disconnect may only be mildly awkward, however in complex interfaces it could make things horribly unusable.

Is it ever OK to change visual order with CSS?

At work I recently reviewed a PR where the visual order of a Flexbox layout was being updated via order: -1 in a media query for wide viewports. Although it was a really elegant solution on paper, I advised caution in light of the pitfalls mentioned above.

However a colleague rightly pointed out that the elements being reordered were two divs. In this case and any others where the elements (and their children) are non-focusable and we’re not messing with the likes of navigation links or form elements, I think we are safe.

The Future

We’ve recently been given a few new CSS layout powers only to subsequently be advised not to use them.

How do we move forward?

Rachel Andrew argues that this problem needs addressed at a CSS level; that developers should be able to set the tab and reading order to follow the visual rather than source order under certain circumstances.

Until that becomes a CSS reality we should continue to be judicious in our usage to ensure we don’t break user expectations. We can also use tools like the Source Order Viewer in Chrome DevTools (DevTools > Elements > Accessibility) to check our work.

A Utility Class for Covering Elements (on CSS { In Real Life })

Need to overlay one HTML element on top of and fully covering another, such as a heading with translucent background on top of an image? Michelle Barker has us covered with this blog post in which she creates an overlay utility to handle this. She firstly shows how it can be accomplished with positioning, then modernises her code using the inset CSS logical property, before finally demonstrating a neat CSS Grid based approach.

I like this and can see myself using it – especially the Grid-based version because these days I try to avoid absolute positioning and use modern layout tools instead where possible.

I’ve mocked up a modified version on Codepen, sticking with CSS Grid for simplicity. I was going to also wrap it in an @supports (display:grid) however the styles are all grid-based so in the case of no grid support they simply wouldn’t run, rather than causing any problems.

Browser Support Heuristics

In web development it’s useful when we can say “if the browser supports X, then we know it also supports Y”.

There was a small lightbulb moment at work earlier this year when we worked out that:

if the user’s browser supports CSS Grid, then you know you it also supports custom properties.

Knowing this means that if you wrap some CSS in an @supports(display:grid) then you can also safely use custom properties within that block.

I love this rule of thumb! It saves you looking up caniuse.com for each feature and comparing the browser support.

This weekend I did some unplanned rabbit-holing on the current state of (and best practices for using) ES modules in the browser, as-is and untranspiled. That revealed another interesting rule of thumb:

any browser that supports <script type="module"> also supports let and constasync/await, the spread operator, etc.

One implication of this is that if you currently build a large JavaScript bundle (due to being transpiled down to ES 3/5 and including lots of polyfills) and ship this to all browsers including the modern ones… you could instead improve performance for the majority of your visitors by configuring your bundler to generate two bundles from your code then doing:

// only one of these will be used. 
<script type="module" src="lean-and-modern.js"></script>
<script nomodule src="bulky-alternative-for-old-browsers.js"></script>

I might make a little page or microsite for these rules of thumb. They’re pretty handy!

Breaking Out With CSS Grid Layout (on cloudfour.com)

While bookmarking the mastery.games article yesterday, I started getting the feeling that something was awfully familiar. It was! I’ve seen this layout before – from Tyler Sticka back in 2017 to be precise – but failed to bookmark it at the time.

Here, then, is the original and still the best CSS Grid “article with breakout images” layout!

I particularly love the way that, by naming the lines and appending -start and -end as appropriate you can then target the area between those lines using its short name.

.Prose {
  display: grid;
  grid-template-columns: 
    [full-start] minmax(1em, 1fr) 
    [main-start] minmax(0, 40em) [main-end]
    minmax(1em, 1fr) [full-end];
}

.Prose > * {
  grid-column: main;
}

.Prose-splash {
  grid-column: full;
}

Article Layout with CSS Grid (on mastery.games)

Very clever responsive <article> layout (with gutters and breakout images) achieved using CSS Grid, minmax(), the ch unit and a minimum of fuss. It scales automatically from narrow to wide viewports with no auto margins, max-width or media query manual overrides in sight.

For the blog post page (the page you're looking at right now) I wanted a mobile-friendly layout where the text was centered and readable, where the images/code examples are wide.

The gist of it is this:

.post {
  display: grid;
  grid-template-columns:
    minmax(1.2rem, 1fr)
    minmax(auto, 57ch)
    minmax(1.2rem, 1fr);
}

Simple and deadly.

I can potentially see this as a pattern, or layout primitive, rather than just as something you might use at the top-level of the page for overall layout. I’m looking forward to trying it out!

(via Ahmad Shadeed)

Modern CSS Solutions

Modern CSS Solutions for Old CSS Problems

Stephanie Eckles with a beautifully presented series of articles on how to use modern CSS to tackle some of the enduring challenges of web development including dropdown navigation, centring and styling buttons.

Old CSS, new CSS (eev.ee)

I first got into web design/development in the late 90s, and only as I type this sentence do I realize how long ago that was. Here’s a history of CSS and web design, as I remember it.

A fantastic and amusing account of how we progressed from no CSS (the early days of font tags, inline styles and tables for layout), through bad browsers, untold hacks and browser prefixes, to the relative luxury of today’s tools such as Flexbox and CSS Grid.

Subgrid for CSS Grid launches in Firefox 71

Subgrid for CSS Grid Layout has arrived in Firefox and it looks great. Here’s how I wrapped my head around the new concepts.

While MDN has some nice examples, I generally find I need a little extra time, trial and error and note-making in order to fully grasp CSS Grid concepts.

For example, I always need to remind myself that parts of the syntax – such as grid-template-columns selectors – refer to grid lines rather than columns.

So I created a Subgrid example pen with guideline notes for future reference. Note: make sure to open the pen in Firefox rather than any other browser, because at the time of writing only Firefox supports Subgrid!

Relearn CSS layout: Every Layout

Every now and then something comes along in the world of web design that represents a substantial shift. The launch of Every Layout, a new project from Heydon Pickering and Andy Bell, feels like one such moment.

In simple terms, we get a bunch of responsive layout utilities: a Box, a Stack, a Sidebar layout and so on. However Every Layout offers so much more—in fact for me it has provided whole new ways of thinking and talking about modern web development. In that sense I’m starting to regard it in terms of classic, game-changing books like Responsive Web Design and Mobile First.

Every Layout’s components, or primitives, are self-governing and free from media queries. This is a great step forward because media queries tie layout changes to the viewport, and that’s suboptimal when our goal is to create modular components for Design Systems which should adapt to variously-sized containers. Every Layout describe their components as existing in a quantum state: simultaneously offering both narrow and wide configurations. Importantly, the way their layouts adapt is also linked to the dynamic available space in the container and the intrinsic width of its contents, which leads to more fluid, organic responsiveness.

Every Layout’s approach feels perfect for the new era of CSS layout where we have CSS Grid and Flexbox at our disposal. They use these tools to suggest rather than dictate, letting the browser make appropriate choices based on its native algorithms.

Intrinsically Responsive CSS Grid with minmax and min

Evan Minto notes that flexible grids created with CSS Grid’s repeat, auto-fill, and minmax are only intrinsically responsive (responsive to their container rather than the viewport) up to a point, because when the container width is narrower than the minimum width specified in minmax the grid children overflow.

Applying media queries to the grid is not a satisfactory solution because they relate to the the viewport (hence why Every Layout often prefer Flexbox to CSS Grid because it allows them to achieve intrinsic responsiveness).

However we’ll soon be able to suggest grid item width as a percentage of the parent container, avoiding the overflow problem. The new “CSS Math functions” to help us achieve this are min(), max() and clamp(). At the time of writing, these are only supported in Safari however Chrome support is in the pipeline.

Katherine Kato’s personal website

Some simple but inspiring work here from Seattle-based web developer Katherine Kato. I really like the use of space, the typography, the colour palette and the use of CSS grid for layout.

Using CSS display: contents to snap grandchild elements to a grid

I realised last night while watching a presentation by Lea Verou that I could streamline my CSS Grid layouts.

I’d been creating an overall page grid by setting body { display: grid; } then some grid areas but realised that this only worked for direct children and didn’t help with aligning more deeply nested elements to that outer grid.

For example in the case of the main header if I wanted its child logo, nav and search elements to snap to the body grid then I found myself having to duplicate the display: grid and grid-template-areas again on the header.

It didn’t feel very DRY but my understanding was that while we await subgrid, it was a necessary evil.

What I should have been using is display: contents.

If you set your header to display: contents then the parent (body) grid layout will apply to the header’s contents (logo, nav, etc) as if the header element (the “real” direct child of the grid) wasn’t there. This gives us good semantics without the need to redefine the grid on the header.

Here’s a codepen to illustrate.

I was aware of the existence of display: contents but somehow it hadn’t sunk in because I’d only read about it in the abstract. Lea Verou’s explanation made all the difference. Cheers, Lea!

Update 4/5/2019

Frustratingly, I’ve learned that although we can apply this technique, we shouldn’t… or at least not for a while.

Due to a bug in all supporting browsers the property will currently also remove the element (header in our case) from the accessibility tree meaning that its semantics will be lost.

For reference, see:

Update 11/4/2021

Thanks to Rachel Andrew for the heads-up that this issue is now fixed in both Firefox and Chrome.

We’re now just waiting for Edge and Safari to roll out fixes before we can regard this as a safe option.

Grid by Example

Great resource from CSS Grid expert Rachel Andrew, with the Patterns and Examples sections which provide quick-start grid layouts being particularly handy.

Using the tabindex attribute | TPG

Léonie Watson explains how the HTML tabindex attribute is used to manage keyboard focus. Of particular interest to me was a clarification of what tabindex="-1" does (because I always forget).

tabindex="-1"

The element becomes programmatically focusable but isn’t included in the tab order. It can’t be reached by someone using the tab key to navigate through content, but it can be focused on with scripting via the focus() method.

We might use this because we want to be able to set focus to a particular element via a script. Léonie offers the example of a list of form errors.

Alternatively we might use this because we want to prevent a normally tabbable element from being tabbable. Sara Souidean uses this technique (in combination with aria-hidden=true) on e-commerce product teaser “media objects” in order to limit the number of duplicate links that keyboard users must tab through.

Tabindex on page targets to assist with keyboard focus

I’ve often seen tabindex="-1" used as a companion to the id attribute on elements of a page intended to be directly accessible via links. Examples include a main element that should be directly accessible from a “Skip to content” link, or the headings in a blog article to support sharing direct links to page sections.

Before HTML5, creating an internal “link target” required creating an anchor element that used the name attribute. In HTML5 this use of anchor was deprecated with authors instead encouraged to add the id attribute to any element they wish. The reason why developers added tabindex="-1" to their main and h2 (etc) “targets” is because some older browsers, when responding to a link to such a resource, would move visual focus to the target element (i.e. scroll to it) but not programatically set focus to it if the target element was not focusable. Including tabindex="-1" solved that problem.

Modern browsers move the focus correctly and so using tabindex for this purpose is no longer necessary.

tabindex="0"

Applying tabindex="0" to an element inserts it into the tabbing order based on its position in the source. It is not necessary to apply this to an interactive element such as a button or checkbox since they are focusable by default. You should use it sparingly (because it requires care to ensure accessibility) but you might use it on a custom element which needs to be interactive under certain circumstances such as the horizontally scrollable container in a Data Table.

tabindex="1+"

This imposes a tab order on the content that bears no resemblance to the expected tab order. It’s an antipattern. Don’t do it.

See all tags.

External Link Bookmark Note Entry Search