justin․searls․co

Adding vertical screen size media queries to Tailwind

Learning Tailwind was the first time I've felt like I had a chance in hell of expressing myself visually with precision and maintainability on the web. I'm a fan. If your life currently involves CSS and you haven't tried Tailwind, you should spend a few days with it and get over the initial learning curve.

One thing I like about Tailwind is that it's so extensible. It ships with utility classes for dealing with screen sizes to support responsive designs, but out-of-the-box it doesn't include any vertical screen sizes. This isn't surprising as they're usually not necessary.

But, have you ever tried to make your webapp work when a phone is held sideways? When you might literally only have 330 pixels of height after accounting for the browser's toolbar? If you have, you'll appreciate why you might want to make your design respond differently to extremely short screen heights.

Figuring out how to add this in Tailwind took less time than writing the above paragraph. Here's all I added to my tailwind.config.js:

module.exports = {
  theme: {
    extend: {
      screens: {
        short: { raw: '(max-height: 400px)' },
        tall: { raw: '(min-height: 401px and max-height: 600px)' },
        grande: { raw: '(min-height: 601px and max-height: 800px)' },
        venti: { raw: '(min-height: 801px)' }
      }
    }
  }
}

And now I can accomplish my goal of hiding elements on very short screens or otherwise compressing the UI. Here's me hiding a logo:

<img class="w-6 short:hidden" src="/logo.png">

Well, almost…

Unfortunately, because of this open issue, defining any screens with raw will inadvertently break variants like max-sm:, which is bad. So in the meantime, a workaround would be to define those yourself. Here's what that would look like:

const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      screens: {
        short: { raw: '(max-height: 400px)' },
        tall: { raw: '(min-height: 401px and max-height: 600px)' },
        grande: { raw: '(min-height: 601px and max-height: 800px)' },
        venti: { raw: '(min-height: 801px)' },

        // Manually generate max-<size> classes due to this bug https://github.com/tailwindlabs/tailwindcss/issues/13022
        'max-sm': { raw: `not all and (min-width: ${defaultTheme.screens.sm})` },
        'max-md': { raw: `not all and (min-width: ${defaultTheme.screens.md})` },
        'max-lg': { raw: `not all and (min-width: ${defaultTheme.screens.lg})` },
        'max-xl': { raw: `not all and (min-width: ${defaultTheme.screens.xl})` },
        'max-2xl': { raw: `not all and (min-width: ${defaultTheme.screens['2xl']})` },
      }
    }
  }
}

Okay, yeah, so this was less of a slam dunk than I initially suggested, but I'm still pretty happy with it!


Got a taste for hot, fresh takes?

Then you're in luck, because you can subscribe to this site via RSS or Mastodon! And if that ain't enough, then sign up for my newsletter and I'll send you a usually-pretty-good essay once a month. I also have a solo podcast, because of course I do.