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

leading-loose unable to override line-height from xl:text-6xl due css definition order #6504

Closed
bithavoc opened this issue Dec 14, 2021 · 7 comments

Comments

@bithavoc
Copy link

bithavoc commented Dec 14, 2021

What version of Tailwind CSS are you using?

3.0.2

What build tool (or framework if it abstracts the build tool) are you using?

  • postcss@8.4.4
  • postcss-cli@9.0.2
  • nextjs or postcss-cli or gulp@4.0.2

What version of Node.js are you using?

  • Node v14.16.1

What browser are you using?

Chrome, Firefox

What operating system are you using?

macOS and Windows

Reproduction URL

https://github.com/widemeshio/bug-tailwind-v3-leading-vs-text-height

Describe your issue

In a brand new Next.js project(or also legacy using v3 and gulp with postcss),
leading-loose css classes are generated before screen size variants(md, xl, etc) so because what matters is the order in which the css classes are defined not in the order they're used in class="", its currently not possible to do something like lg:text-6xl leading-loose because lg:text-6xl's line-height takes priority. text-6xl leading-loose works though, so this is specific about screen size variants.

Example code:

     <main className="w-1/4">
        <h3 className="text-6xl leading-loose text-green-600">
          text-6xl + leading (OK)
        </h3>
        <h3 className="lg:text-6xl leading-loose text-red-600">
          lx:text-6xl + leading (Buggy)
        </h3>
      </main>

Inspector:

image

Page View:

image

@reinink
Copy link
Member

reinink commented Dec 14, 2021

Hey! So this is actually expected behavior, which you can find explained in the documentation here:

https://tailwindcss.com/docs/line-height#breakpoints-and-media-queries

It’s important to note that by default, Tailwind’s font-size utilities each set their own default line-height. This means that any time you use a responsive font-size utility like sm:text-xl, any explicit line-height you have set for a smaller breakpoint will be overridden.

<!-- The `leading-loose` class will be overridden at the `md` breakpoint -->
<p class="text-lg leading-loose md:text-xl">
  Maybe we can live without libraries...
</p>

If you want to override the default line-height after setting a breakpoint-specific font-size, make sure to set a breakpoint-specific line-height as well:

<!-- The `leading-loose` class will be overridden at the `md` breakpoint -->
<p class="text-lg leading-loose md:text-xl md:leading-loose">
  Maybe we can live without libraries...
</p>

Using the same line-height across different font sizes is generally not going to give you good typographic results. Line-height should typically get smaller as font-size increases, so the default behavior here usually saves you a ton of work. If you find yourself fighting it, you can always customize your font-size scale to not include default line-heights.

Hope that helps! 💪

@reinink reinink closed this as completed Dec 14, 2021
@bithavoc
Copy link
Author

Amazing, thanks @reinink 🚀

@pljspahn
Copy link

This is kind of bugging me. I am using line-height to center text vertically:

    <div class="w-full h-24">
        <a href="{% url 'current-sale-list' %}" class="font-display italic leading-[6rem] lg:leading-[6rem] text-2xl lg:text-6xl" >
            {{settings.utils.BannerSettings.banner_text}}
        </a>
    </div>

I'd like to just keep the line height at 6rem at all breakpoints since the parent is set to h-24 (6rem), but since it gets overridden I'm forced to declare it twice. Once for default and once again for because lg:text-6xl overrides it.

Not really a big deal but it's kind of confusing at first and repeating the same style twice feels gross. I've never really liked centering text vertically is done in CSS, so maybe I should use a different method, but I generally prefer this method.

@reinink
Copy link
Member

reinink commented Aug 16, 2022

@pljspahn Hey, if you don't want this behavior, you can disable the size-specific line-heights. You can read more about this in the Tailwind CSS v2 upgrade guide here: https://v2.tailwindcss.com/docs/upgrading-to-v2#configure-your-font-size-scale-explicitly

Basically just update the fontSize property in your tailwind.config.js file to only include the font sizes, and not the line-height values.

// tailwind.config.js
module.exports = {
  theme: {
    fontSize: {
      xs: '0.75rem'
      sm: '0.875rem'
      base: '1rem'
      lg: '1.125rem'
      xl: '1.25rem'
      2xl: '1.5rem'
      3xl: '1.875rem'
      4xl: '2.25rem'
      5xl: '3rem'
      6xl: '3.75rem'
      7xl: '4.5rem'
      8xl: '6rem'
      9xl: '8rem'
    },
  }
}

@pljspahn
Copy link

Thanks.

I'm happy leaving the default config alone, and for now I've added a plugin text-vert where I can set line-height, height, and font-size explicitly on the element:

    plugin(function({matchUtilities, theme}) {
        matchUtilities(
            {
                'text-vert': (value) => ({
                    lineHeight: value+'rem',
                    height: value+'rem',
                    fontSize: value/2+'rem',
                }),
            },
            { values: theme('lineHeight') },
        )
    }),

I had avoided figuring out plugins previously but I suppose now is as good a time as any to learn it.

@MichaelAllenWarner
Copy link
Contributor

@pljspahn and any lurkers:

If you want to keep the line-heights in your default text- classes but still have the option to set only the font-size, I think you can accomplish this with a custom text-size- utility that references your theme's fontSize values:

matchUtilities(
  {
    'text-size': (value) => ({ fontSize: value }),
  },
  {
    values: Object.fromEntries(
      Object.entries(theme('fontSize') || {}).map(([key, value]) => [
        key,
        Array.isArray(value) ? value[0] : value,
      ])
    ),
  }
);

@asgarovf
Copy link

asgarovf commented Mar 6, 2024

@pljspahn Hey, if you don't want this behavior, you can disable the size-specific line-heights. You can read more about this in the Tailwind CSS v2 upgrade guide here: https://v2.tailwindcss.com/docs/upgrading-to-v2#configure-your-font-size-scale-explicitly

Basically just update the fontSize property in your tailwind.config.js file to only include the font sizes, and not the line-height values.

// tailwind.config.js
module.exports = {
  theme: {
    fontSize: {
      xs: '0.75rem'
      sm: '0.875rem'
      base: '1rem'
      lg: '1.125rem'
      xl: '1.25rem'
      2xl: '1.5rem'
      3xl: '1.875rem'
      4xl: '2.25rem'
      5xl: '3rem'
      6xl: '3.75rem'
      7xl: '4.5rem'
      8xl: '6rem'
      9xl: '8rem'
    },
  }
}

Some formattings:

module.exports = {
  theme: {
    fontSize: {
      xs: '0.75rem',
      sm: '0.875rem',
      base: '1rem',
      lg: '1.125rem',
      xl: '1.25rem',
      '2xl': '1.5rem',
      '3xl': '1.875rem',
      '4xl': '2.25rem',
      '5xl': '3rem',
      '6xl': '3.75rem',
      '7xl': '4.5rem',
      '8xl': '6rem',
      '9xl': '8rem',
    },
  }
}

adamwathan added a commit that referenced this issue Sep 18, 2024
… utilities with font-size utility defaults (#14403)

This PR improves how the `text-{size}` utilities interact with the
`leading-*`, `tracking-*`, and `font-{weight}` utilities, ensuring that
if the user explicitly uses any of those utilities that those values are
not squashed by any defaults baked into the `text-{size}` utilities.

Prior to this PR, if you wrote something like this:

```html
<div class="text-lg leading-none md:text-2xl">
```

…the `leading-none` class would be overridden by the default line-height
value baked into the `text-2xl` utility at the `md` breakpoint. This has
been a point of confusion and frustration for people [in the
past](#6504) who are
annoyed they have to keep repeating their custom `leading-*` value like
this:

```html
<div class="text-lg leading-none md:text-2xl md:leading-none lg:text-4xl lg:leading-none">
```

This PR lets you write this HTML instead but get the same behavior as
above:

```html
<div class="text-lg leading-none md:text-2xl lg:text-4xl">
```

It's important to note that this change _only_ applies to line-height
values set explicitly with a `leading-*` utility, and does not apply to
the line-height modifier.

In this example, the line-height set by `text-sm/6` does _not_ override
the default line-height included in the `md:text-lg` utility:

```html
<div class="text-sm/6 md:text-lg">
```

That means these two code snippets behave differently:

```html
<div class="text-sm/6 md:text-lg">…</div>
<div class="text-sm leading-6 md:text-lg">…</div>
```

In the top one, the line-height `md:text-lg` overrides the line-height
set by `text-sm/6`, but in the bottom one, the explicit `leading-6`
utility takes precedence.

This PR applies the same improvements to `tracking-*` and
`font-{weight}` as well, since all font size utilities can also
optionally specify default `letter-spacing` and `font-weight` values.

We achieve this using new semi-private CSS variables like we do for
things like transforms, shadows, etc., which are set by the `leading-*`,
`tracking-*`, and `font-{weight}` utilities respectively. The
`text-{size}` utilities always use these values first if they are
defined, and the default values become fallbacks for those variables if
they aren't present.

We use `@property` to make sure these variables are reset to `initial`
on a per element basis so that they are never inherited, like with every
other variable we define.

This PR does slightly increase the amount of CSS generated, because now
utilities like `leading-5` look like this:

```diff
  .leading-5 {
+   --tw-leading: 1.25rem;
    line-height: 1.25rem;
  }
```

…and utilites like `text-sm` include a `var(…)` lookup that they didn't
include before:

```diff
  .text-sm {
    font-size: 0.875rem;
-   line-height: var(--font-size-sm--line-height, 1.25rem);
+   line-height: var(--tw-leading, var(--font-size-sm--line-height, 1.25rem));
  }
```

If this extra CSS doesn't feel worth it for the small improvement in
behavior, we may consider just closing this PR and keeping things as
they are.

This PR is also a breaking change for anyone who was depending on the
old behavior, and expected the line-height baked into the `md:text-lg`
class to take precedence over the explicit `leading-6` class:

```html
<div class="text-sm leading-6 md:text-lg">…</div>
```

Personally I am comfortable with this because of the fact that you can
still get the old behavior by preferring a line-height modifier:

```html
<div class="text-sm/6 md:text-lg">…</div>
```

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
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

No branches or pull requests

5 participants