Tagged “responsive”
First play with CSS Container Queries
In responsive design we generally want a single component to get different styles in different contexts. Up until recently the prevailing method of context-awareness was to use a CSS media query to query the viewport size. This wasn’t ideal. For example you might want an component to be styled differently when in a narrow context such as a sidebar (regardless of the device size), and viewport-based queries don’t help with that.
But everything has changed. We can now use CSS to query the size of any given container and this feature is supported in all major browsers.
There’s a bit of new syntax to learn, so I recently had my first play with container queries on codepen.
My pen is pretty trivial, but the goal was specifically to do the most minimal test that lets me test-drive the key syntax. It turns out that it’s quite straightforward.
Define an element as a container:
.sidebar {
container: ctr-sidebar / inline-size;
}
Change the styles of another element (.foo
) when it’s inside that container and the container’s inline-size (the logical property name for width
) matches a given query:
@container ctr-sidebar (max-width: 300px) {
.foo {
// context-specific styles go here
}
}
Note that you could also omit the ctr-sidebar
context in the above query, if you wanted the change to apply in all defined containers.
Displaying tables on narrow screens
Responsive design for tables is tricky. Sure, you can just make the table’s container horizontally scrollable but that’s more a developer convenience than a great user experience. And if you instead try to do something more clever, you can run into challenges as I did in the past. Still, we should strive to design good narrow screen user experiences for tables, alongside feasible technical solutions to achieve them.
In terms of UI design, I was interested to read Erik Kennedy’s recent newsletter on The best way to display tables on mobile. Erik lists three different approaches, which are (in reverse order of his preference):
- Hide the least important columns
- Cards with rows of Label-Value pairs
- More radical “remix” as a “Mobile List”
Another article worth checking is Andrew Coyle’s The Responsive Table. He describes the following approaches:
- Horizontal overflow table (inc. fixed first column)
- Transitional table
- Priority responsive table
For the transitional table, Andrew links to Charlie Cathcart’s Responsive & Accessible Data Table codepen. It looks similar (perhaps better looking but not quite as accessible) to Adrian Roselli’s Responsive Accessible Table.
Getting started with Utopia Figma Plugins (Utopia Blog)
Here’s another tool from the Utopia creators to assist with breakpoint-free fluid responsive design.
Until now, the tooling for Utopia has been predominantly developer-focused, but we know that's only half the story. To start to address this, we've created a pair of Figma plugins to help designers set out Utopian project foundations.
I also really like the idea of having three sets of type styles at both defined viewport sizes.
We typically use a Strong style for headings and other text that we want to visually punctuate our designs. The Prose style is useful for longer-form text which might benefit from a larger, more relaxed line height. The Default style is a catch-all for other snippets of text in our designs, like a standlone link, a short piece of explainer text, or perhaps an image caption. The number and variety of styles required will vary depending on your design's purpose and style but these three serve as a reasonable starting point.
inline-block versus flexbox for horizontal arrangements
Something I’ve found interesting while reviewing recent code test submissions (within job applications) at work is that more developers than I’d expect still use display: inline-block
when they need to lay out multiple elements horizontally such as the items in a navigation menu. It’s interesting because Flexbox – which has now been around for almost 10 years – gives you a modern, purpose-built solution to that.
Of course, there is no crime in taking the inline-block
approach. It’s an option. And I did take a moment just to challenge my assumptions. But having given it a little thought, I am pretty convinced that Flexbox is the better approach and so I think their choice is worth a query.
Here’s why I think Flexbox is much better:
- Modern CSS layout is purpose-built for constructing multi-element layouts. Older methods were lacking, quirky and slightly hacky. Using (and knowing to use) purpose-built tools is generally a good thing for reliability, predictability and scalability.
- Modern CSS layout provides more control, because it’s fundamentally different. You get a parent context (the flex container or grid) that lets you style the context (with
gap
, for example). We didn’t have this before. - Styling a context rather than individual items plays better with modern component-oriented organisation and ideas. It‘s good to keep components encapsulated and context-agnostic, handing off layout to separate, fit-for-purpose tools.
- Flexbox is built for responsiveness, i.e. built for the modern era.
inline-block
was not. - the default
align-items:stretch
means that items laid out in a row are automatically full parent-height which is often desirable for larger touch targets and achieving hover styles. inline-block
retains some of the properties ofinline
that are undesirable for this type of use-case. Who can be bothered with whitespace in the code appearing on the screen, or having to work withvertical-align
when you don’t need to.
I also don’t see any reason to not use Flexbox. It’s conventional (see for example navigation menus on BBC, Tetralogical), recommended by CSS experts (Rachel Andrew, Jen Simmons etc), performant and well-supported by browsers. You are not going “fancy”, “cutting edge” or “overkill” by using Flexbox. For the “horizontal menu” use case, it’s simply a more suitable choice than the older alternatives.
Related: Chris Coyier’s article When do you use inline block is an excellent investigation into whether any necessary uses for inline-block
remain. I reserve the right to change my mind on this, but aside from the “apply transform
to an inline element” use case I can’t really see any that have not now been superseded.
My new syntax for modern, responsive blog images
I’ve started trialling different HTML and technologies for the “simple” responsive images (i.e. not art-directed per breakpoint) used in blog articles on this site. I’m continuing to lean on Cloudinary as my free image host, CDN and format-conversion service. But at the HTML level I’ve moved from a complicated <img srcset>
based approach that includes many resized versions of the same image. I now use a simpler <picture>
and <source>
based pattern that keeps the number of images and breakpoints low and instead – by using the source element’s type
attribute – takes advantage of the performance gains offered by the new avif
and webp
image formats.
My new approach is based on advice in Jake Archibald’s brilliant article Halve the size of images by optimising for high density displays. Jake explains that the majority of your traffic likely consists of users with high density screens so when we can combine optimising for that and making performance gains in a progressively enhanced way, we should!
Jake offers a “lazy but generally good enough” approach:
Here's the technique I use for most images on this blog: I take the maximum size the image can be displayed in CSS pixels, and I multiply that by two, and I encode it at a lower quality, as it'll always be displayed at a 2x density or greater. Yep. That's it. For 'large' images in blog posts like this, they're at their biggest when the viewport is 799px wide, where they take up the full viewport width. So I encode the image 1,598 pixels wide.
<picture>
<source type="image/avif" srcset="red-panda.avif" />
<source type="image/webp" srcset="red-panda.webp" />
<img src="red-panda.jpg" width="1598" height="1026" alt="A red panda" />
</picture>
So, if you want your images to be as sharp as possible, you need to target images at the user's device pixels, rather than their CSS pixels. To encode a 2x image, I throw it into Squoosh.app, and zoom it out until it's the size it'll be displayed on a page. Then I just drag the quality slider as low as it'll go before it starts looking bad.
Taking Jake’s guidance and tweaking it for my Cloudinary-based context, my recent post April 2022 mixtape included its image like so:
<figure>
<picture>
<source type="image/avif" srcset="https://res.cloudinary.com/…/f_avif,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" />
<source type="image/webp" srcset="https://res.cloudinary.com/…/f_webp,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" />
<img class="u-full-parent-width" src="https://res.cloudinary.com/…/f_jpg,q_auto,w_1292/v1654433393/mato_1500_squooshed_mozjpg_xjrkhl.jpg" width="1292" height="1292" alt="Side A of the 7-inch vinyl release of Mato’s “Summer Madness" loading="lazy" decoding="async" />
</picture>
<figcaption>Mato’s “Summer Madness”, as featured on the mix</figcaption>
</figure>
And my process was as follows:
- Take a photo (for me, that’ll be on my phone). Without doing anything special it’ll already be wide enough.
- Apple use the HEIC format. To get around that, do: Share, Copy, open Files > HEIC to JPG, paste and it’ll save as JPG.
- Drop it into Squoosh and do the following:
- rotate it if necessary
- resize it to 1300 wide (in my current layout
1292
is twice as wide (2 × 646) as the image would need to go, and I just round up to 1300) - reduce its quality a bit (stopping before it gets noticeably bad)
- Encode that as a
mozjpg
which gave the best size reduction and as far as I can tell, is a safe approach to use. - Upload to my Cloudinary account then copy its new Cloudinary URL.
- Prepare the image HTML per the above snippet. The first
source
tells Cloudinary to use formatavif
, while for the second source it’swebp
, and for the fallbackimg
it’sjpg
. - Check the rendered image in a browser to confirm that the modern formats are being used.
I’ll DRY-up that HTML into an 11ty shortcode in due course.
I’ve no doubt that I’ll be getting some of this wrong – this stuff gets pretty complicated! For example I note my image file size is still quite large so I wonder if I should be manually creating the avif
and webp
versions in Squoosh myself to ensure getting the savings that make this approach worthwhile, rather than handing the conversion off to Cloudinary. (However this would mean having to host more images…)
In the meantime however, I’m happy that this approach has simplified the mental overhead of handling modern, responsive blog images, and optimising it can be a work in progress.
Additional references
Min-Max clamp calculator, by 9elements
Here’s a handy tool from the smart folks at 9elements for making a value – such as a font-size, or margin – fluidly responsive. In their words the tool…
calculates the CSS clamp formula to interpolate between two values in a given viewport range.
It’s inspired by Utopia but is for situations when you only need a single clamp formula rather than one for each interval in a type or spacing scale.
Beyond that, the website for this tool just looks great and is choc-full of tricks. It uses some snazzy CSS, includes Zach Leatherman’s details-utils web component for animated disclosures and is made with Astro, Svelte and PostCSS.
Partnering with Google on web.dev (on adactio.com)
At work in our Design System team, we’ve been doing a lot of content and documentation writing for a new reference website. So it was really timely to read Jeremy Keith of Clearleft’s new post on the process of writing Learn Responsive Design for Google’s web.dev resource. The course is great, very digestible and I highly recommend it to all. But I also love this new post’s insight into how Google provided assistance, provided a Content handbook as “house style” for writing on web.dev and managed the process from docs and spreadsheets to Github. I’m sure there will be things my team can learn from that Content Handbook as we go forward with our technical writing.
Theming to optimise for user colour scheme preference
“Dark mode” has been a buzz-phrase in web development since around 2019. It refers to the ability provided by modern operating systems to set the user interface’s appearance to either light or dark. Web browsers and technologies support this by allowing developers to detect whether or not the OS provides such settings, and if so which mode the user prefers. Developers can create alternate light and dark themes for their websites and switch between these intelligently (responsively?) to fit with the user’s system preference.
I’ve been meaning to do some work on this front for a while and finally got around to it. (You might even be reading this post with your computer’s dark colour scheme enabled and seeing the fruits of my labour.) Here’s how I set things up and the lessons I learned along the way.
Switching your computer’s appearance
On a Mac:
System Preferences > General > Appearance
On Windows:
Colors > Choose your color
On iOS:
Settings > Display & Brightness > Appearance
On Android:
Settings > Dark Theme
Emulating this in browser DevTools
In Chromium-based browsers you can open DevTools, then open the Rendering
tool (which might be hidden behind More Tools). In the Emulate CSS media feature prefers-color-scheme dropdown, select prefers-color-scheme: dark or prefers-color-scheme: light.
The theme-color HTML meta tag
You can use the theme-color
HTML meta tag to indicate to the browser a colour it can use to customise the display of the page and surrounding elements such as the address bar. The reason we have a meta tag solution to this rather than leaving it to CSS is performance; it allows the browser to make the relevant updates immediately.
In practice you might specify your “highlight colour”—Clearleft currently use their signature green. Alternatively you could specify both your light theme and dark theme background colours, using the media
attribute to associate each with the user colour scheme preference it is optimised for. This is the approach I chose.
<!-- Set theme color to white when user prefers light mode -->
<meta name="theme-color" content="rgb(255,255,255)" media="(prefers-color-scheme: light)">
<!-- Set theme color to a custom black when user prefers dark mode -->
<meta name="theme-color" content="rgb(38,38,38)" media="(prefers-color-scheme: dark)">
The theme-color meta tag has mixed support. It works well in Safari and iOS Safari. Meanwhile Chrome only applies the colour on installed progressive web apps (PWAs).
This had me considering PWA matters again for the first time in a while. I previously definined a PWA “theme colour” for my website in my manifest.manifest
file. However unlike in the theme-color
meta tag approach, the manifest allows defining one theme colour only. While I don’t think there’d be any issue in having both the meta tag and manifest value in play simultaneously (my understanding is that the HTML would take priority over the manifest), I decided to keep things simple and removed theme_color
from my manifest file for now.
Note: the w3c manifest spec may support multiple theme colours in future.
The color-scheme meta tag
The color-scheme
meta tag is used to specify one or more color schemes/modes with which the page is compatible. Unlike theme-color
you don’t provide an arbitrary colour value, but rather one of light
or dark
or both in combination. This tells the browser whether it can change default background, foreground and text colours to match the current system appearance. As Jim Nielsen notes in Don’t forget the color-scheme property, it gives the browser permission to automatically change standard form controls, scroll bars, and other named system colors.
I include this meta tag on each page (just after my theme-color
meta tags). I indicate that my styles have been prepped to handle the browser applying either light or dark colour schemes and—via the order of values in the content attribute—that I prefer light.
<meta name="color-scheme" content="light dark">
Notes:
- I’ve also seen
<meta name="supported-color-schemes">
however Thomas Steiner explained that this is an old syntax and has since been standardised as<meta name="color-scheme">
; - There is also a
color-scheme
CSS property, which I’ll come to later. Once again though, having an HTML meta tag helps browsers to apply things faster; - although I’m currently intimating that I prefer light, in future I might update this to dark first (assuming I don’t hear of any reasons against it). The dark colour palette is really growing on me!
Ensuring colours are accessible
While working on a new dark colour palette and tweaking my light palette I made sure to check that colour contrast met accessibility requirements.
Useful tools on this front include:
- Activating Chrome’s element inspector (the “box with arrow at bottom-right” icon) enables hovering an element to check the contrast of text against background;
- Erik Kennedy’s Accessible Color Generator provides slightly modified colour alternatives when contrast is insufficient—really handy and I used this a couple of times;
- Are my colors accessible? is another great “check contrast, digest results, then tweak” tool which provides more detailed information than the Chrome inspector, especially regarding the impact of small text on contrast.
Design Tokens
It quickly became clear that I’d need global colour settings that I could use across multiple technologies and multiple files. For example, I’d want to reuse the same custom background colour value in an HTML theme-color
meta tag, in CSS, and perhaps also in a JSON-based manifest file.
I’d previously bookmarked Heydon Pickering’s article on design tokens in Eleventy and now was the time to give it a spin.
I created _data/tokens.json
in which I defined raw tokens such as colorDark
, colorDarker
and colorLight
.
Then in my Nunjucks-based HTML templates I could access that token data to define meta tag values using {{ tokens.colorLight }}
. These values would be interpolated to the real CSS colour values during build.
I also created a new Nunjucks file, theme_css.njk
, adding permalink: "css/theme.css"
in its frontmatter so that it’d generate a CSS file. This file maps my design tokens to custom properties set on the root element, something like this:
:root {
--color-dark: {{ tokens.colorDark }};
--color-darker: {{ tokens.colorDarker }};
--color-light: {{ tokens.colorLight }};
--color-grey: {{ tokens.colorGrey }};
--color-highlight: {{ tokens.colorHighlight }};
--color-highlight-dark: {{ tokens.colorHighlightDark }};
--color-highlight-darker: {{ tokens.colorHighlightDarker }};
--color-text: {{ tokens.colorText }};
}
Custom properties FTW
Using custom properties allowed me to do the hard work of preparing my light and dark themes upfront and removed the need to constantly duplicate values and write code forks throughout my CSS.
Having previously created a base layer of reusable custom property representations of my design tokens, I began creating more specific custom properties to serve different contexts.
:root {
--color-page-bg-light: var(--color-light);
--color-page-bg-dark: var(--color-dark);
--color-ink-dark: var(--color-text);
--color-ink-light: var(--color-light);
}
CSS for default and dark-mode contexts
Now to set my light-mode defaults and fork these when the user prefers dark-mode.
Here’s my CSS:
:root {
color-scheme: light;
--color-highlight: var(--color-highlight-darker);
--color-page-bg: var(--color-page-bg-light);
--color-band: var(--color-darker);
--color-ink: var(--color-ink-dark);
--color-ink-offset: var(--color-grey);
@media (prefers-color-scheme: dark) {
color-scheme: dark;
--color-highlight: var(--color-highlight-dark);
--color-page-bg: var(--color-page-bg-dark);
--color-band: var(--color-darker);
--color-ink: var(--color-ink-light);
--color-ink-offset: var(--color-grey);
}
accent-color: var(--color-highlight);
}
body {
background-color: var(--color-page-bg);
color: var(--color-ink);
}
Let’s break that down.
The color-scheme
property allows us to specify one or more colour schemes/modes with which an element is compatible. I’m defining it on the root element i.e. for the whole page. My approach was to start by specifying support for a light colour scheme only, then define background and text colour custom properties with values optimised for light colour scheme.
Using @media (prefers-color-scheme: dark) {…}
we can check the user’s colour scheme preference. When the user prefers dark, I change color-scheme
to dark
to let the browser do its “set sensible defaults” thing, and I update the custom property values to those optimised to blend with a dark appearance.
The reusable, theme-sensitive custom properties I’ve plumped for are:
- highlight colour: really just my brand colour, although lightened a touch in dark mode for better contrast;
- page background colour;
- “band” background colour: something I’d use as a band of alternative background colour to distinguish special sections like the header or footer;
- ink colour: my default text colour;
- “offset” ink colour: a grey for little bits of meta text like dates and categories.
I’m sure I’ll evolve these over time.
Lastly, the accent-colour
CSS property is used by some form controls e.g. radios and checkboxes. I set that to my highlight colour with the intention of creating a more branded experience.
SVG considerations
My SVG-based logo didn’t look right in dark mode, however the fix was pretty simple. I applied BEM-style element classes to any problematic path
elements of the SVG then wrote CSS for those. The CSS tests for prefers-color-scheme: dark
and updates the path’s fill
or stroke
colour as necessary.
What about leaving everything to the browser?
Having read Jim Nielsen’s brilliant article on CSS System Colors I tried feeding the browser color-scheme: light dark
, removing my arbitrary dark theme colours, and leaving the colour palette entirely up to the browser. Along the way I learned some interesting lessons on system colours—which we can also choose to use as valid CSS colours in our custom components—such as Canvas
and CanvasText
.
I love this idea in principle! However in practice:
- only Safari’s colour palette looks consistent with the rest of the Mac OS. The palette applied by Chrome doesn’t; it has its own, different “black”. So for the control you’ve given away, you don’t necessarily achieve that nice “consistency with the OS” reward in return;
- as far as I know you can’t lighten or darken the system colours so it’s hard to create a multi-tone, complimentary palette, and also be confident in achieving sufficient colour contrast. That’s fine if you only need a single background colour for the entire page with no alternate bands of colour (like on Jim’s blog) however I think that’s a little restrictive. (Maybe I’m getting too hung up on control here though, and introducing additional arbitrary colours would work fine alongside a variable “system black”);
- Firefox and iOS Safari are a little problematic in their support for the technologies involved, leading to writing a few hacky workarounds.
For the combined reasons above I’m sticking with manually defined colours for now (however I have a pull request I can revisit later if the mood takes).
What could I do better?
With extra time, I might:
- think more deeply about dark theme design, perhaps following some of the tips regarding shadows, depth and colour contrast in CSS Tricks’ A complete guide to dark mode on the web;
- consider providing a theme switcher control to allow the user to choose the website theme they want regardless of the current OS appearance. (But I probably won’t; I’m not sure it’s necessary)
References
- Theming, from Jeremy Keith’s excellent Learn Responsive Design
- Design Tokens in Eleventy by Heydon Pickering
- CSS System Colors by Jim Nielsen
Learn Responsive Design (on web.dev)
Jeremy Keith’s new course for Google’s web.dev learning platform is fantastic and covers a variety of aspects of responsive design including layout (macro and micro), images, icons and typography.
Conditional border-radius in CSS (by Ahmad Shadeed via CSS-Tricks)
Here’s a “media query free” CSS one-liner which lets you set an element to have no border-radius when it is the full width of the viewport, but otherwise to have a border-radius.
It uses the same 9999 multiplication technique as Every Layout do to create a toggle.
Great for Card components which need to be full-width and non-rounded only on narrow viewports.
Doppler: Type scale with dynamic line-height
line-height
on the web is a tricky thing, but this tool offers a clever solution.
It’s relatively easy to set a sensible unit-less default ratio for body text (say 1.5
), but that tends to need tweaked and tested for headings (where spacious line-height doesn’t quite work; but tight line-height is nice until the heading wraps, etc).
Even for body text it’s a not a one-size-fits-all where a line-height like 1.5
is appropriate for all fonts.
Then you’ve got different devices to consider. For confined spaces, tighter line-height works better. But this can mean you might want one line-height for narrow viewports and another for wide.
Then, factor in vertical rhythm based on your modular type and spacing scales if you really want to blow your mind.
It can quickly get really complicated!
Doppler is an interesting idea and tool that I saw in CSS-Tricks’ newsletter this morning. It lets you apply line-height
using calc()
based on one em
-relative value (for example 1em
) and one rem
-relative value (for example 0.25rem
).
In effect you’ll get something like:
set line-height to the font-size of the current element plus a quarter of the user’s preferred font-size
The examples look pretty promising and seem to work well across different elements. I think I’ll give it a spin.
Swipey image grids (on cassie.codes)
A lovely post by Cassie Evans in which she demonstrates that SVG is not just for icons and illustrations. You might also reach for it to create a responsive, animated grid of images.
we have another grid at our disposal. SVG has its own internal coordinate system and it's responsive by design.
There are lots of interesting techniques in here such as:
- layering an
<image>
on top of a shape such as a<rect>
; - using
preserveAspectRatio
to make the image fully cover and fit the shape when their aspect ratios differ; - using
<clipPath>
as a custom-shaped window to an image (for example a<circle>
); - giving the
<clipPath>
’s nested shape a solidfill
to hide the<image>
to which it’s applied; - animating a rectangular
<clipPath>
applied to an image to give the effect of the image “sliding into view”; and - using Greensock to make sequencing multiple animations easy and to ensure they work consistently across browsers.
However I also loved this simple piece of practical advice to help picture the SVG’s viewbox
and plot shapes on top:
I usually get a pen and paper out at this point and doodle it out.
Use CSS Clamp to create a more flexible wrapper utility (on Piccalilli)
Here’s Andy Bell recommending using CSS clamp()
to control your wrapper/container width
because it supports setting a preferred value in vw
to ensure sensible gutters combined with a maximum tolerance in rem
—all in a single line of code.
If we use clamp() to use a viewport unit as the ideal and use what we would previously use as the max-width as the clamp’s maximum value, we get a much more flexible setup.
The code looks like this:
.container {
width: clamp(16rem, 90vw, 70rem);
margin-left: auto;
margin-right: auto;
}
This is pretty cool because I know from experience that coding responsive solutions for wrappers can be tricky and you can end up with a complex arrangement of max-width and media queries whilst still—as Andy highlights—not providing optimal readability for medium-sized viewports.
Using CSS Grid with minmax() is one possible approach to controlling wrappers however this article offers another (potentially better) tool for your kit.
It’s worth noting that Andy could probably have just used width: min(90vw, 70rem)
here (as Christopher suggested) because setting the lower bound provided by clamp()
is only necessary if your element is likely to shrink unexpectedly and a regular block-level element wouldn’t do that. The clamp
approach might be handy for flex items, though.
(via @piccalilli_)
Comparing Browsers for Responsive Design (on CSS-Tricks)
Chris Coyier checks out Sizzy, Polypane et al and decides which suits him best.
There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing CSS and making sure it’s working across all the viewports in a single glance.
I noticed Andy Bell recommending Sizzy so I’m interested to give it a go. Polypane got Chris’s vote, but is a little more expensive at ~£8 per month versus ~£5, so I should do a little shoot-out of my own.
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;
}
Minimalist Container Queries
Scott Jehl’s experimental take on a container/element query aimed at letting us set responsive styles for our elements based on their immediate context rather than that of the viewport.
I made a quick and minimal take on approximating Container/Element Queries using a web component and basic CSS selectors.
The idea is that for any given instance of the <c-q>
custom element / web component you would define a scoped custom property which sets the pixel min-widths you’re interested in, like so:
c-q {
--breakpoints: "400 600 800";
background: black;
}
Zero to many of those numeric min-width
values will appear in the element’s data-min-width
HTML attribute based on which (if any) of them the element’s width is equal to or greater than.
You can style the element based on their presence using the ~=
attribute selector, like this:
c-q[data-min-width~="400"] {
background: green;
}
c-q[data-min-width~="600"] {
background: blue;
}
See also Scott’s tweet announcing this which contains some interesting contributions including Heydon’s watched-box.
All of the various JavaScript approaches/experiments are summarised in CSS-Tricks’s article Minimal Takes on Faking Container Queries.
(via @scottjehl)
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.
Responsive Type and Zoom (by Adrian Roselli)
When people zoom a page, it is typically because they want the text to be bigger. When we anchor the text to the viewport size, even with a (fractional) multiplier, we can take away their ability to do that. It can be as much a barrier as disabling zoom. If a user cannot get the text to 200% of the original size, you may also be looking at a WCAG 1.4.4 Resize text (AA) problem.
I already tend to avoid dynamic, viewport-width-based fluid typography techniques in favour of making just one font-size adjustment – at a desktop breakpoint – based on the typographic theory that suggests we adjust type size according to reading distance. I learned this in Richard Rutter’s excellent book Web Typography.
While the ideas and code behind the fluid typography approach are nice, Adrian’s discovery that it can hinder users who need to zoom text only strengthens my feeling that it’s not the best way to handle responsive type.
The Size of Space (on neal.fun)
This interactive, web-based tool which lets you swipe through various space objects to see their relative size is pretty cool, really nicely done, and handy whenever you could use a dose of perspective! (via @adactio)
You don’t need a media query for that: #1 Inline content separators
Create a more flexible component which allows the text to wrap based on the content rather than the viewport size.
Here, Mandy Michael explores similar territory to Every Layout in suggesting that not all responsive pattern challenges require, or indeed are best served by, media queries.
The example here is a pipe-separated text pair (I could imagine an author and publish date meta line) which Mandy wants to wrap (with pipe separator hidden) only when the content and container require it, rather than based on the less-relevant viewport width.
She uses a clever combination of flex-wrap:wrap
, generated content, padding, transform
and overflow-y:hidden
to achieve her goal.
(Via @Mandy_Kerr)
Polypane: The browser for responsive web development and design
Polypane is a browser built specifically for developing responsive websites. It can present typical device resolutions side-by-side (for example iphone SE next to iphone 7 next to iPad) but also has some nice features such as automatically creating views based on your stylesheet’s media query breakpoints.
It’s a subscription service and at the moment I’m happy using a combination of Firefox Nightly and Chrome so I think I’ll wait this one out for the time being. But I’ll be keeping my eye on it!
A Dao of Web Design (on A List Apart)
John Allsopp’s classic article in which he looks at the medium of web design through the prism of the Tao Te Ching, and encourages us to embrace the web’s inherent flexibility and fluidity.
It’s time to throw out the rituals of the printed page, and to engage the medium of the web and its own nature.
It’s choc-full of quotable lines, but here are a few of my favourites:
We must “accept the ebb and flow of things.”
Everything I’ve said so far could be summarized as: make pages which are adaptable.
…and…
The web’s greatest strength, I believe, is often seen as a limitation, as a defect. It is the nature of the web to be flexible, and it should be our role as designers and developers to embrace this flexibility, and produce pages which, by being flexible, are accessible to all. The journey begins by letting go of control, and becoming flexible.
See all tags.