Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use progressive maxWidth scale #701

Merged
merged 3 commits into from Mar 5, 2019
Merged

Use progressive maxWidth scale #701

merged 3 commits into from Mar 5, 2019

Conversation

adamwathan
Copy link
Member

@adamwathan adamwathan commented Mar 1, 2019

This PR changes the default maxWidth scale from a linear (jumps of 10rem) scale to a progressive scale, where the values towards the bottom end are closer together and the values towards the top are more spread out.

It also increases the total number of values from 9 to 12.

Old scale on left, new scale on right (click to zoom):

image

You can also see the values at their actual size in this CodePen:

Preview the new maxWidth scale in the browser

The maxWidth utilities are pretty important to get right because they are (IMO) the best way to create "fixed" width blocks in a UI, like the first card in this screenshot from Netlify:

image

...or this sign in form taken from Baremetrics:

image

They are also useful for constraining a block of content, like this paragraph from Stripe's homepage:

image

I think the values in this new scale are pretty good, but one thing I'm unsure about is if we should have values that match all of the default breakpoints as well, and if so, should they just be part of the scale, or given different names?

I find it is very common in my own projects to create utilities like max-w-screen-md that sets an element's max width to match the medium screen size for example. In fact, if those values existed, the container component would really just be a shortcut for:

<div class="w-full sm:max-w-screen-sm md:max-w-screen-md lg:max-w-screen-lg xl:max-w-screen-xl">
  <!-- ... -->
</div>

...so I think it kind of makes sense for those values to exist if you ever needed to break out of some of the behavior provided by the container and drop to a lower level primitive.

So I'm wondering if people have opinions on that, how useful they would find it based on what they've done on previous projects, and how adding those would impact this new scale. Does this new scale really need to go all the way up to 9xl if we are adding the screen size options?

Any input and examples of when/how you use max-width utilities would be much appreciated.

@shadyendless
Copy link

I usually find that the current values for the maxWidth scale aren't too useful for me, and the image you posted demonstrates why pretty well.

It's hard to design things that scale relationally when the scale is constant - I often find that I can't fine-tune or find the necessary values with the existing, constant, scale requiring me to add my own maxWidth values.

I'm not sure that the proposed 1.x scale would solve all of my problems, but I do believe it is definitely a more sensible default as I could see myself adding fewer custom values than I do now. This has my non-authoritative approval ;)

@michaelmoussa
Copy link

michaelmoussa commented Mar 1, 2019

I'm super new to Tailwind here (so forgive me if this is crazytalk!), but is this something that it might make sense to make user-configurable? For example, user sets some kind of scale value to indicate they want linear vs. progressive, as well as an steps value to indicate how many jumps (minimum of 5, because xs/sm/md/lg/xl - anything higher than 5 would be <#>xl).

So, doing nothing will make whatever the current setup is available, specifying scale = "progressive", steps = 12 will give you the setup you proposed above, and scale = "linear", steps = 10 (just for example!) will give you 10 options ranging from <min> to <max> in jumps of (<max> - <min>) / <steps - 1> units.

If made generic enough, maybe this would be applicable to all things that supported range sizing like fonts and such?

@bdrtsky
Copy link

bdrtsky commented Mar 2, 2019

If scale ratio will be predefined, then it's too opinionated and doesn't make sense to me. Why I should stick with particular predefined settings, and how to remember them? It's ok for Typography, but not clear why maxWidth should be as a scale?

@autumnwoodberry
Copy link

The max width I usually need most often is something like max-w-screen-sm or max-w-screen-md

@adamwathan
Copy link
Member Author

These would just be the default values, and of course can be completely customized just like everything else in Tailwind by specifying the values you want for your own project in your config file:

module.exports = {
  theme: {
    maxWidth: {
      // Your values go here...
    },
  },
}

@adamwathan
Copy link
Member Author

I noticed this morning that this maxWidth scale actually already includes every default breakpoint except sm, which is 568px, whereas this scale has a 576px value.

I've opened another PR proposing changing that breakpoint back to 576px to match this new maxWidth scale, but I'm still not sure it's the best solution.

Here's what I wrote there as I think it's equally relevant to this conversation:

Keeping it at 576px means every default screen size has a matching maxWidth helper, without having to introduce new max-w-screen-* utilities on top of the regular maxWidth scale. The motivation for 568px was because that's the height of an iPhone SE, but (very sadly) I doubt we will see devices of that size ever again, so since most (almost all?) people use larger mobile devices, it's actually probably better that this breakpoint is wider because you get to use a little more of the available screen real estate. The iPhone 6/7/8 for example has a height of 667px, so with a 576px breakpoint, we're still wasting 91px, and with 568px we were wasting 99px.

The only thing that sucks is that even though this change means there is always a matching maxWidth for every default breakpoint, there is no logical mapping between them. The sm breakpoint is is max-w-xl for example, and the lg breakpoint is max-w-5xl. There's no way to make max-w-sm match the sm breakpoint and max-w-md match the md breakpoint because there's a maxWidth value that sits in between those two screen sizes, and I'd have no idea what to name it.

We could introduce aliases, so max-w-xl would also be defined as max-w-screen-sm, but that would be the first time we've ever done anything like that in the framework.

Really not sure what to do here.

Would love any input/ideas 👍

@adamwathan
Copy link
Member Author

I'm super new to Tailwind here (so forgive me if this is crazytalk!), but is this something that it might make sense to make user-configurable? For example, user sets some kind of scale value to indicate they want linear vs. progressive, as well as an steps value to indicate how many jumps (minimum of 5, because xs/sm/md/lg/xl - anything higher than 5 would be <#>xl).

@michaelmoussa Hey and welcome! Definitely an interesting idea, but I think the most flexible approach is to allow people to customize the entire scale directly and arbitrarily like we already do vs. trying to create an abstraction around it that tries to generate values. Appreciate the input though 👍

@AlexVipond
Copy link
Contributor

AlexVipond commented Mar 2, 2019

The only thing that sucks is that even though this change means there is always a matching maxWidth for every default breakpoint, there is no logical mapping between them. The sm breakpoint is is max-w-xl for example, and the lg breakpoint is max-w-5xl. There's no way to make max-w-sm match the sm breakpoint and max-w-md match the md breakpoint because there's a maxWidth value that sits in between those two screen sizes, and I'd have no idea what to name it.

I think this is a strong case for using numeric naming system and free up the t-shirt size names to map directly to screen sizes. For example:

maxWidth: {
  '1': '20rem',
  '2': '24rem',
  '3': '28rem',
  '4': '32rem',
  ...,

  'sm': '568px',
  'md': '768px',
  'lg': '1024px',
  'xl': '1280px',
}

Then, there's no need to specify max-w-screen-*, we can just use the shorter max-w-sm.

Only downside is that this might lead to some confusion with the numbered width utilities. For example w-4 is 1rem but max-w-4 is 32rem. I still prefer that, as long as we can map t-shirt sizes directly to screen sizes.

Remember also that if anyone changes their base font-size while max-widths are in rem, the px screen sizes would no longer match up to max-width utilities, so it would be good to have them available separately.

@adamwathan
Copy link
Member Author

@AlexVipond Thanks so much for the well-considered feedback 👍 I agree in a perfect world a linear numeric scale is a really nice idea, I like that idea even for the regular margin/padding scales too but have opted not to explore it for 1.0 because there are advantages to the proportional scale too, and the cost of that breaking change would be pretty high 😕

Remember also that if anyone changes their base font-size while max-widths are in rem, the px screen sizes would no longer match up to max-width utilities, so it would be good to have them available separately.

This is a really great point! I think for this reason there's really no point in trying to have the maxWidth scale contain the default breakpoints, it makes a lot more sense for them to exist as extra values on top of the scale 👍 The only question then is how does that affect the scale 🤔 Do we really need values all the way up to 1280/1440 if we aren't concerned about matching breakpoints anymore? Maybe we only need stuff in the ~300-900 range? Going to study some existing interfaces and see what sort of examples I can find.

@shadyendless
Copy link

@AlexVipond I actually really like the idea of having the numeric scale and the breakpoint scale separate like that.

@adamwathan couldn't this also automatically populate the breakpoint scales based on the configured breakpoints that Tailwind already knows about? Seems like it could be an elegant solution.

@adamwathan
Copy link
Member Author

Yeah we can autopopulate based on the breakpoints easily, that's no problem. I hesitate to use a linear numeric scale because we don't do that anywhere else in Tailwind. The internal rule has always sort of been "numeric scales are proportional, t-shirt size scales are progressive". For that reason I would probably still stick with max-w-sm and the like for the scale, and explicit values like max-w-screen-md for the breakpoints.

Somehow I skipped 6xl? I'm an idiot.
Now that I plan to add max-w-screen-* variations, I don't think these huge options provide any real value.
@adamwathan
Copy link
Member Author

Removed the largest two options (7xl and 8xl) since I plan to add screen-* variations and don't want things to get bloated, especially since I don't think those values are really valuable with max-w-screen-xl in there as well.

Also fixed a dumb error where I went straight from 5xl to 7xl, so now the scale goes from xs to 6xl.

New scale:

https://codepen.io/adamwathan/pen/QoNBJW

@AlexVipond
Copy link
Contributor

AlexVipond commented Mar 2, 2019

@adamwathan thanks!

To be clear, I'm suggesting using proportional numeric naming for max-width, just like you do with width and height. Mostly because it just feels a little awkward to get all the way up to 9xl (that's one hell of a t-shirt!) and whenever I add values, stuff like 6.5xl always feels funky.

(To be even clearer I'm probably going to customize my config to use linear numeric naming on everything 🤫)

@hacknug
Copy link
Contributor

hacknug commented Mar 3, 2019

LGTM although I'd go with a numeric proportional scale. Even if it doesn't include all values the spacing scale does, it would make it easier to extend than the current t-shirt scale.

@adamwathan
Copy link
Member Author

To be clear, I'm suggesting using proportional numeric naming for max-width, just like you do with width and height.

@AlexVipond Sorry I think we are probably using the word proportional differently — in your example you listed these values:

maxWidth: {
  '1': '20rem',
  '2': '24rem',
  '3': '28rem',
  '4': '32rem',
}

...which in my mind aren't proportional, at least not in the way that the spacing/width/height scale is. max-w-2 should be twice the size of max-w-1, and max-w-4 should be twice the size of max-w-2, etc. Agree though 9xl is quite a large t-shirt, haha... I tweaked it to end at 6xl now which seems a little less ridiculous.

LGTM although I'd go with a numeric proportional scale. Even if it doesn't include all values the spacing scale does, it would make it easier to extend than the current t-shirt scale.

@hacknug Do you mean something like this?

    maxWidth: {
      80: '20rem',
      96: '24rem',
      112: '28rem',
      128: '32rem',
      144: '36rem',
      168: '42rem',
      192: '48rem',
      224: '56rem',
      256: '64rem',
      288: '72rem',
    },

It would be consistent with the spacing scale but seems really hard to learn those numbers

@hacknug
Copy link
Contributor

hacknug commented Mar 3, 2019

Yup, you're right. Don't mind me 😄

@adamwathan adamwathan merged commit 1ffa750 into next Mar 5, 2019
@adamwathan adamwathan deleted the new-max-width-scale branch March 5, 2019 14:44
@wjthomas9
Copy link

Removed the largest two options (7xl and 8xl) since I plan to add screen-* variations and don't want things to get bloated, especially since I don't think those values are really valuable with max-w-screen-xl in there as well.

When do you plan to work in the screen-* variations?

@AlexVipond
Copy link
Contributor

@wjthomas9 and anyone else watching this—with the new config file, you can easily create breakpoint utilities on your own:

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      maxWidth: {
        'screen-sm': defaultTheme.screens.sm,
        'screen-md': defaultTheme.screens.md,
        'screen-lg': defaultTheme.screens.lg,
        'screen-xl': defaultTheme.screens.xl
      }
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants