Displaying CSS Breakpoint Information with Generated Content

Published 6 years, 9 months past

In the course of experimenting with an example design for my talks at An Event Apart this year, I came up with a way to keep track of which breakpoint was in force as I tested the design’s responsiveness.  I searched the web to see if anyone else had written about this and didn’t come up with any results, so I’ll document it here.  And probably also in the talks.

What I found was that, since I was setting breakpoints in ems instead of pixels, the responsive testing view in browsers didn’t really help, because I can’t maintain realtime mapping in my head from the current pixel value to however many rems it equals.  Since I don’t think the browser has a simple display of that information, I decided I’d do it myself.

It starts with some generated content:

body::before {content: "default";
   position: fixed; top: 1px; right: 1px; z-index: 100; padding: 1ch;
   background: rgba(0,0,0,0.67); color: rgba(255,255,255,0.75);
   font: bold 0.85rem Lucida Grande, sans-serif;}

You can of course change these to some other placement and appearance.  You can also attach these styles to the html element, or your page wrapper if you have one, or honestly even the footer of your document — since the position is fixed, it’ll be viewport-relative no matter where it originates.  The real point here is that we’re generating a bit of text we can change at each breakpoint, like so:

@media (max-width: 38em) {
   body::before {content: "<38em";}
   /* the rest of the breakpoint styles here */
}
@media (max-width: 50em) {
   body::before {content: "<50em";}
   /* the rest of the breakpoint styles here */
}
@media (min-width: 80em) {
   body::before {content: ">80em";}
   /* the rest of the breakpoint styles here */
}

The labels can be any string you want, so you can use “Narrow”, “Wide”, and so on just as easily as showing the measure in play, as I did.

The downside for me is that we automatically can’t make the labels cumulative in native CSS.  That means the order the @media blocks appear will determine which label is shown, even if multiple blocks are being applied.  As an example, given the styles above, at a width of 25em, the label shown will be <50em even though both the 38em and 50em blocks apply.

There are ways around this, like switching the order of the max-width blocks so the 38em block comes after the 50em block.  Or we could play specificity games:

@media (max-width: 38em) {
   html body::before {content: "<38em";}
   /* the rest of the breakpoint styles here */
}
@media (max-width: 50em) {
   body::before {content: "<50em";}
   /* the rest of the breakpoint styles here */
}

That’s not a solution that scales, sadly.  Probably better to sort the max-width media blocks in descending order, if you think you might end up with several.

The upside is that it’s easy to find and remove these lines once the development phase moves to QA.  Even better, before that point, you get a fully customizable in-viewport indication of where you are in the breakpoint stack as you look at the work in progress.  It’s pretty trivial to take this further by also changing the background color of the little box.  Maybe use a green for all the block above the “standard” set, and a red for all those below it.  Or toss in little background image icons of a phone or a desktop, if you have some handy.

So that’s the quick-and-dirty little responsive development hack I came up with this morning.  I hope it’s useful to some of you out there — and, if so, by all means share and enjoy!


Addendum: Emil Björklund proposes a variant approach that uses CSS Custom Properties (aka CSS variables) to implement this technique.


Comments (10)

  1. Was the second breakpoint in “specificity games” supposed to be something like @media (min-width:38em) and (max-width: 50em)? As written, it looks like it doesn’t solve the problem.

  2. This made me think of Jeremy’s old question about detecting MQ:s in JS, to which I contributed a similar solution.

    I remember discussing at the time that CSS Variables would make that (task of communicating between CSS and JS) easier, but it was too early then to use them. Today, and for your use-case, I think they could be perfect though!

    Something like this, maybe?

    body::after {
       content: var(--bp, 'narrow');
    }
    
    @media (min-width: 25em) {
      :root {--bp: '>=25em'}
    }
    

    JSBin demo here.

  3. rossry, the difference was actually the selector in the first block, which added an html to raise the selector’s specificity. Like I said, not a very scalable solution.

    Emil, I think that’s a good use of variables. I may write a followup that explains that usage with credit to you, unless you’d rather write it up and I’ll add an addendum to this post pointing to your writeup.

  4. Pingback ::

    Pixels of the Week – February 23, 2018 - Stéphanie Walter, Visual and UX Designer, Mobile enthusiast

    […] Eric’s Archived Thoughts: Displaying CSS Breakpoint Information with Generated Content […]

  5. Eric: thanks for the suggestion – I wrote a quick piece about the technique (and background) on my blog. Cheers!

  6. Pingback ::

    CSS for debugging media queries – Mostly Tech Stuff

    […] Eric Meyer: Displaying CSS Breakpoint Information with Generated Content […]

  7. Yeah, this is simple but sweet. I’m using this technique with Pattern Lab, adding a named breakpoint in a content property, and feeding the pseudo-element with breakpoint names from a Sass map.

    Also, by rendering this to the Pattern Lab scaffolding CSS, it’s only shown in development mode, i.e. in Pattern Lab, but never ends up in the production styles.

    The breakpoint Sass map is also used to populate another hidden pseudo-element (in production CSS) containing the named breakpoint to be used by JS – in order to keep the list of breakpoints in one place only; in CSS. Essentially the very same solution that Emil mentions in his blog post, using getComputedStyle.

  8. This is something I’ve used on my localhost/staging sites for a while. While the sample code uses pixel units for breakpoints, it can easily be adapted to use em, rem, or whatever other unit you need.

    In this instance, i’m using a SCSS map to style the breakpoint helper a bit, and to give it a hover effect with the full scss breakpoint variable name.

    https://codepen.io/kgcreative/pen/XZobRW

    The bit of jquery at the end only ammends an aside with the breakpoint-helper class if you are on your locahost, a staging server (or in this case, codepen). I did that to harden the code a bit so the breakpoint helper element wouldn’t travel to production by mistake.

    Feel free to use/adapt

  9. Trackback ::

    Netz - Rettung - Recht

    Wellenreiten 02/2018

    Wer als “Websurfer” metaphorisch auf den Wellen des Netzes reitet, findet dabei zwar keine paradiesischen Inseln, manchmal aber immerhin ganz interessante Lektüre. Im Februar 2018 kann ich u.a. folgende Fundstücke empfehlen und der werten L…

  10. How about:

    @media screen and (max-width: 38em) {...}
    @media screen and (min-width: 38em) and (max-width: 50em) {...}
    @media screen and (min-width: 50em) and (max-width: 80em) {...}
    @media screen and (min-width: 80em) {...}

    wouldn’t that solve the issue of a width that matches more than one media query, as defined in your code?

Add Your Thoughts

Meyerweb dot com reserves the right to edit or remove any comment, especially when abusive or irrelevant to the topic at hand.

HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <em> <i> <q cite=""> <s> <strong> <pre class=""> <kbd>


if you’re satisfied with it.

Comment Preview