fontsource icon indicating copy to clipboard operation
fontsource copied to clipboard

Customizable font-display value

Open iquito opened this issue 5 years ago • 27 comments

As far as I can tell, all fonts have a setting of font-display: swap; which cannot be changed. For my applications I would prefer font-display: fallback, which has the following properties: a very short blocking period and a short swap period, after which the font is not swapped anymore, because if the font does not load it is not the end of the world (in my case), while a late swap might impact user experience in a bad way.

https://calendar.perfplanet.com/2020/a-font-display-setting-for-slow-connections/ also has some interesting insights about why font-display: fallback or font-display: optional can be better settings for slow connections. Ideally there would be a way to select the desired font-display strategy, as different applications might have different requirements.

Thanks for the great package! It is a huge step up from typeface-inter, which I used before.

iquito avatar Dec 26 '20 17:12 iquito

Would #64 fit as a suitable resolution to your problem? While it is easy to make SASS files customisable, I don't know if there are any alternatives that could apply variables to the CSS. Nor do I believe generating even more CSS files to account for every possibility is the right step forward.

ayuhito avatar Dec 26 '20 18:12 ayuhito

I am using quite a "vanilla" Webpack + TailwindCSS configuration, so it would be preferable to not add SASS as a dependency, because I am not using it otherwise. This is basically the opposite of #64, where someone didn't want to use Webpack and use SASS instead. For me I have the full Webpack / PostCSS setup but no SASS, because when using Tailwind you usually don't need much CSS or any processors for it, except for Tailwind itself.

I am not the biggest expert in terms of the front end tooling, but maybe the CSS could be generated in Javascript, which would make it easy to add configuration? This would be a completely different way of generating the CSS, but it would make any type of customization easier compared to pre-generated CSS files. Settings like font-display would not need to be included at all (leaving it at the browser default) except if an application wants to specify the behavior through customization.

iquito avatar Dec 26 '20 18:12 iquito

I'm not necessarily sure how to go ahead implementing that, but it is a plausible idea. Another alternative to consider could be utilising PostCSS to create a plugin that makes the CSS configurable.

I'd be open to hearing from other developers on their ideas and of course, PRs are welcomed.

ayuhito avatar Dec 26 '20 18:12 ayuhito

If PostCSS can help with this it would definitely be a good option, as PostCSS is always part of TailwindCSS projects and most other projects using Webpack. Tailwind also supports plugins, which might be another option with its growing popularity.

iquito avatar Dec 26 '20 18:12 iquito

I've done this by writing the following as a postcss plugin (putting it in the plugins array in postcss.config.css):

{
  postcssPlugin: true,
  Declaration: {
    'font-display': (node) => {
      if (node.parent.name === 'font-face' && node.parent.type === 'atrule') node.value = 'optional'
    }
  }
}

It sets all font-display rules to optional if they are in a @font-face rule.

While this isn't a complete solution, it might help someone, and it could possibly be integrated into a plugin.

nathanchu avatar Jan 19 '21 14:01 nathanchu

I've created #133 for PostCSS specific discussion. This issue can still be used to discuss other viable alternatives.

ayuhito avatar Jan 20 '21 15:01 ayuhito

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. Use the 'not stale' label to prevent the issue from automatically closing.

stale[bot] avatar Feb 19 '21 16:02 stale[bot]

I believe this shouldn't be closed. It's definitely still an issue and as much as I appreciate having a workaround I would love to have a simple non-hacky way to specify the font-display value! I don't want my titles to show until their fonts have been loaded :)

callumgare avatar Sep 07 '22 00:09 callumgare

@callumgare, I'm actively working on #558 (#555 for font-display) where downloading the fonts will serve as an escape hatch to do anything you want.

There's no "easy" way to change the CSS in the NPM package as it is purely static and stuck in the limitations of node_modules. This is the easiest compromise I can offer.

ayuhito avatar Sep 07 '22 06:09 ayuhito

@ayuhito Thanks for the update! If I'm understanding #555 correctly the idea is that you would manually download those fonts, commit them into your app repo, and then you can just simply use your own @font-face block to pull them in and customise the css however you like?

Personally I perfectly happy managing the @font-face css block myself. However the thing I find really valuable about fontsource is that it will manage the downloading of those font files so I don't need to commit them to my repo. I love that I can treat them like any other dependency and have npm worry about making sure I have them downloaded when needed. What I want (but didn't think was possible until I'm realising just now that it is) is be able to keep using fontsource to download those font files and then just import them from the node_modules directory with my custom css @font-face block. I didn't think this was possible because when I tested it I was using url('node_modules/@fontsource/forum/files/forum-latin-400-normal.woff2') format('woff2'), url('node_modules/@fontsource/forum/files/forum-latin-400-normal.woff') format('woff') as my src css property. I'm using the SveltKit framework and the SveltKit dev server that works fine with that but when building for production it wasn't importing that file correctly. However I've just discovered if I skip the node_modules/ part it works fine.

So to anyone else wanting to do this try copying out the @font-face block from the css file that fontsource would normally import, then replace ./files/ in the src property with @fontsource/<directory of font you're using>/files/. I want to use npm to download the fonts since I don't want to have to commit those fonts to my repo.

Thanks again @ayuhito for getting me on the right path, much appreciate your work on fontsource!

callumgare avatar Sep 13 '22 03:09 callumgare

So to anyone else wanting to do this try copying out the @font-face block from the css file that fontsource would normally import, then replace ./files/ in the src property with @fontsource/<directory of font you're using>/files/. I want to use npm to download the fonts since I don't want to have to commit those fonts to my repo.

This is really interesting. I'll have to see if other bundlers behave similarly to this as a possible alternative escape hatch.

ayuhito avatar Sep 13 '22 18:09 ayuhito

@ayuhito

There's no "easy" way to change the CSS in the NPM package as it is purely static and stuck in the limitations of node_modules. This is the easiest compromise I can offer.

You can refer to a CSS prop + fallback:

font-display: var(--fontsource-font-display, swap);
or
font-display: var(--fontsource-<fontname>-font-display, swap);

And then we just define an override constant in the app code, if we need another value.

CSS props are well supported https://caniuse.com/css-variables , unless you aim to cover very old browsers.

ivan-kleshnin avatar Sep 15 '22 07:09 ivan-kleshnin


font-display: var(--fontsource-font-display, swap);

or

font-display: var(--fontsource-<fontname>-font-display, swap);

This is actually genius, CSS vars completely slipped my mind!

It'd have to be the latter for font specificity (maybe longer names for different weights and style), but this does sound great! I wonder if this should be applied elsewhere too.

Thanks so much, I'll have to try this out as part of v5.

ayuhito avatar Sep 15 '22 07:09 ayuhito

That's the reverse side of tool abundance in modern Web Dev. So easy to forget something basic. Thank you for supporting this library and good luck with v5 ✋

ivan-kleshnin avatar Sep 15 '22 08:09 ivan-kleshnin

I'd love some final feedback on what the CSS variables should look like as I'm close to implementing it and I never want to make another breaking change again.

My current thought process is that we should only have a CSS variable for font-display. We have it automatically set to a default of swap and users can add their own variable to change the display value. If the browser doesn't support CSS variables... it's really not a big deal if they get default font-display blocking behaviour. A few versions older and the browsers don't support WOFF2 anyways 🤷

I'm currently thinking --fontsource-<fontname>-display is a good variable name, but part of me wants to reduce that to a shorter name such as --fontsource-display to bring CSS sizes down more (which is somewhat significant relatively speaking). I think wanting different font-display behaviour for different weights and styles is questionable, thus I'm not going to include it in the default behaviour. Personally, I also don't really see much justification for different font-display values for different fonts, but I may be wrong about that.

One of the biggest things to note is that the new release will allow users to download fonts themselves without NPM easily. So if you need escape hatches for very niche behaviour, there is a solution. Hence why I feel more comfortable going the shorter route to minimise CSS output.

ayuhito avatar Oct 27 '22 02:10 ayuhito

I'd go with --fontsource-display because it's shorter and you set it once for all fonts, if other people need to set it per-font/per-variation, they could write their own CSS and import the font file directly from the package (I have done this before and it works just fine).

jwr1 avatar Oct 27 '22 12:10 jwr1

I think wanting different font-display behaviour for different weights and styles is questionable, thus I'm not going to include it in the default behaviour.

👍 I can't think of a single time in my career I applied different font-display to different weights or styles... It's typically one rule per project, depending on what you hate more: FOUT or FOIT. I hate FOUT more, as it shifts the layout, so I never pick swap, but that's another topic.

ivan-kleshnin avatar Oct 28 '22 07:10 ivan-kleshnin

I agree with --fontsource-display

vitorbarbosa19 avatar Dec 19 '22 11:12 vitorbarbosa19

Hi, this would be a great feature to have, any updates?

kkimdev avatar Feb 25 '23 11:02 kkimdev

@kkimdev, it has been implemented for V5 (#590). Main blocker for V5 release as of now is Sass and finishing up the accompanying website (#597) which I hope to release soontm.

ayuhito avatar Feb 26 '23 04:02 ayuhito

@ayuhito Very nice! Do you have any - very rough - ETA?

kkimdev avatar Feb 27 '23 01:02 kkimdev

@kkimdev, I don't want to make any promises as I have very tangled up commitments at the moment, but I hope to have everything ready mid-March. 😅

ayuhito avatar Feb 27 '23 01:02 ayuhito

Regardless when it'll be done, I really appreciate you as a happy user of fontsource. Thank you ! =D

kkimdev avatar Feb 27 '23 08:02 kkimdev

For reference, V5 is pretty much finished (except for the sass templates) and you can find all the new packages in the new font-files repository. Feel free to review things there and offer any suggestions!

Once the website is ready, we'll publish the update :D

ayuhito avatar Mar 03 '23 14:03 ayuhito

Released in v5 🎉 Check out the documentation here.

ayuhito avatar May 21 '23 09:05 ayuhito

Reopening due to #726.

ayuhito avatar May 25 '23 13:05 ayuhito

Has anyone made this work with Remix? I'm exporting links with css stylesheets like this:

export const links: LinksFunction = () => [
  { rel: 'stylesheet', href: fontStylesheet }, // the css for the font loaded from fontsource package
  { rel: 'stylesheet', href: stylesheet }, // my custom css where I define the var --fontsource-display: optional;
];

And it doesn't work. I've ended up using patch-package (just in case is useful for someone) to edit the file from fontsource but not the ideal solution 🤔

pedro199288 avatar Nov 05 '23 18:11 pedro199288

Just discovered this thread. I'm going with a pnpm patch solution since we're pnpm users.

statico avatar Apr 06 '24 00:04 statico

A solution that also works with Vite-based frameworks is writing your own @font-face declaration:

 @font-face {
    font-family: 'Poppins';
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url('@fontsource/poppins/files/poppins-latin-400-normal.woff2')
      format('woff2');
  }

Vite will automatically rewrite the URL import which can work in our favour. However, this can be burdensome to write when you have many different subsets and weights to support.

With the release of our CDN integration, I think it'll be quite easy to make a similar page that will help autogenerate the necessary CSS for users who still want to use the NPM package, while giving some more flexibility. The steps to then change font-display is to create your own CSS file and import the generated code - and if you want to make any additional adjustments, you'll have full freedom to do so.

I'll look into making a new page for this soon. It shouldn't take too long.

ayuhito avatar Apr 10 '24 14:04 ayuhito

Closed in #954. This is just an escape hatch that simplifies writing custom @font-face declarations by auto-generating the CSS for you.

ayuhito avatar Apr 11 '24 01:04 ayuhito