Make WordPress Core

Opened 5 years ago

Last modified 2 months ago

#47925 new enhancement

Twenty Nineteen: Size of style.css seems excessively large (225% as large as the next largest theme's CSS)

Reported by: westonruter's profile westonruter Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 5.0
Component: Bundled Theme Keywords: has-patch
Focuses: css, performance Cc:

Description (last modified by westonruter)

I just did a check of the size of each core theme's style.css and here's what I found (first column is byte size):

  221622 twentynineteen/style.css
   98458 twentyfifteen/style.css
   83559 twentyseventeen/style.css
   81216 twentyfourteen/style.css
   70311 twentysixteen/style.css
   57356 twentyeleven/style.css
   57106 twentythirteen/style.css
   37606 twentytwelve/style.css
   24688 twentyten/style.css

The style.css for Twenty Nineteen is 225% the size of the next-largest core theme stylesheet, for Twenty Fifteen. Between 5.2.2 and 5.3-alpha, the size of Twenty Nineteen's CSS has grown yet another 9KB.

Prior to Twenty Nineteen, themes primarily had their CSS hand-written, I believe. As of Twenty Nineteen, SASS was used for the first time. Depending on how SASS is written, a little bit of code can end up generating a lot of CSS. Is this the case here for Twenty Nineteen? It doesn't seem the large amount of CSS is directly due to styling blocks, since the other themes have also been updated to style blocks.

A large amount of CSS has negative impact on performance. Not only does it increase the amount of time to render the page (as CSS is render-blocking) through increased data transfer time and CSS parsing time, it also hurts performance once the page has loaded, as there is more CSS in memory and more selectors to be evaluating.

How can the amount of CSS in Twenty Nineteen be reduced to be more in-line with the other core themes?


A few resources related to CSS performance:

Attachments (1)

47925.diff (29.7 KB) - added by sabernhardt 2 months ago.
groups similar font rules with :is(), moves or reformats comments that do not fit and/or help much in final stylesheet, removes WOFF

Download all attachments as: .zip

Change History (18)

#1 @westonruter
5 years ago

  • Description modified (diff)

#2 @westonruter
5 years ago

  • Description modified (diff)

#3 @westonruter
5 years ago

  • Description modified (diff)

#4 follow-up: @marybaum
5 years ago

I wonder if it’s all getting used. I’ve seen mention of a tool that shows which rules are active in a site and which aren’t, so my inclination would be to start there.

Then i’d Look to see if the thing is responsive or mobile-first, bc at least some rules can stay the same from {min-width: 0} to JumboTron size. For example.

And then would come my favorite, replacing floats with Flexbox for things that line up in one direction or Grid for things that lay out in two dimensions. Combine that with a mobile-first stylesheet and we can take a bath towel to a good 40% of a tightly written responsive sheet.

Then we can look for places to hit with a squeegee. 😜

#5 @SergeyBiryukov
5 years ago

I've encountered a similar issue with the wporg-support theme in #meta2479.

The theme's usage of SASS' extend feature caused some excessively verbose selectors, most of which were never used and created unnecessary bloat, even hitting a limit on CSS selector length in some cases.

Extending In Sass Without Creating A Mess is a good reading on using extend more efficiently.

At a glance, a large part of the file is taken up by font family declarations with non-latin fallbacks, coming from _mixins-master.scss, which does use extend. If we find a way to optimize them, it should reduce the file size in half.

#6 in reply to: ↑ 4 @westonruter
5 years ago

Replying to marybaum:

I wonder if it’s all getting used. I’ve seen mention of a tool that shows which rules are active in a site and which aren’t, so my inclination would be to start there.

Also, a lot of the language-specific styles seem like they would be better added via PHP inline styles based on what the actual active language is.

#7 @kjellr
5 years ago

Off the top of my head, I can provide a few additional details.

Depending on how SASS is written, a little bit of code can end up generating a lot of CSS. Is this the case here for Twenty Nineteen? It doesn't seem the large amount of CSS is directly due to styling blocks, since the other themes have also been updated to style blocks.

It could definitely be a part of it! I'm sure the SASS could use a refactor — nobody's been available to take that on since the theme launched, but it would be incredibly welcome.

Regarding the block styling: Twenty Nineteen does include more extensive styling for the core blocks than the other core themes do (for instance, the off-center alignments), so I'd definitely expect the blocks code to be just a little heavier at least.

Then i’d Look to see if the thing is responsive or mobile-first, bc at least some rules can stay the same from {min-width: 0} to JumboTron size. For example.

And then would come my favorite, replacing floats with Flexbox for things that line up in one direction or Grid for things that lay out in two dimensions. Combine that with a mobile-first stylesheet and we can take a bath towel to a good 40% of a tightly written responsive sheet.

Everything should be mobile first, and reliant on flexbox already — though I haven't stayed on top of every commit, so I wouldn't say I'm 100% positive on that one. 😅

At a glance, a large part of the file is taken up by font family declarations with non-latin fallbacks​, coming from _mixins-master.scss​, which does use extend. If we find a way to optimize them, it should reduce the file size in half.

Also, a lot of the language-specific styles seem like they would be better added via PHP inline styles based on what the actual active language is.

Yes, exactly. I think this is a huge part of the CSS bloat, and would probably offer the biggest quick win. Those language-specific font fallbacks were a beast to build, and provide a lot of extra code (most of which is unused for many users). You can find some details on the current (and previous) implementation here:

#45731

These are really screaming for a better solution.

Last edited 5 years ago by SergeyBiryukov (previous) (diff)

#8 @westonruter
5 years ago

  • Summary changed from Twenty Nineteen: Size of style.css seems excessively large (225% larger than next largest theme's CSS) to Twenty Nineteen: Size of style.css seems excessively large (225% as large as the next largest theme's CSS)

#9 @sabernhardt
2 years ago

  • Focuses css added
  • Keywords needs-patch added
  • Milestone changed from Awaiting Review to Future Release
  • Type changed from defect (bug) to enhancement

#10 @karmatosed
3 months ago

  • Keywords close added

I wanted to look back at this due to quite a long time having passed. My inclination would be to close but I know this could still be quite important. As it doesn't have a patch though and is waiting for that but the theme has been out a while, perhaps I can recommend that with some considerations form relevant people @sabernhardt @westonruter - flagging you both for thoughts.

#11 @westonruter
3 months ago

It seems like it should still be fixed. From Web Almanac 2022, it seems that Twenty Nineteen would be near the 90th percentile for CSS usage.

Nevertheless, if no one has capacity to fix, then I guess it would be a wontfix.

#12 @karmatosed
3 months ago

  • Keywords close removed

Ok let's leave this open for now then if someone does want to resolve. We aren't desperate to close things if someone does have the capacity.

#13 @sabernhardt
3 months ago

Reducing or replacing the non-latin fonts section is a big opportunity but tricky, and it would require a lot of testing.

I had thought the theme's use of :lang() would help when a page has multiple languages.

  • It adjusts the font for elements such as headings, inputs and buttons in another language. That could be important to continue supporting (in a different way within style.css?).
  • The font does not adjust for elements that I think are more likely to have their own lang attribute: p, ul, li, div, span and i.
  • Note: since the post editor canvas was moved inside an iframe without a lang attribute in WP6.3, these language styles do not apply there (GB52777 / GB54150).

Less significant opportunies to reduce size:

  • Replace /* */ comments syntax with // when they do not add value to the compiled stylesheets. For example, the mixins file prints comments out of context. I also think that the _normalize comments are not very helpful in the final CSS (except for the credit at the top).
    -4.2KB from those two files
  • #60408 may replace most of the .entry .entry-content selectors.
    -3.1KB just in the block-related rulesets if using :root .site, up to 21.5KB if both classes can be removed from about 1,000 selectors
  • I think the WOFF fallback is unnecessary for the non-breaking space override now. The font affects (Apple) devices with Hoefler Text, and the override is (mainly) intended for Chrome.
    -2.9KB

Maybe this ticket could take care of the comments and WOFF changes, and then another ticket could address the non-latin font fallbacks/overrides if someone discovers a good strategy for that.

Last edited 3 months ago by sabernhardt (previous) (diff)

#14 @westonruter
3 months ago

For all the non-latin fonts section (105 KB), there is a lot of duplication.

There are 31 separate rules, each which have the same selectors aside from the :lang(). For the properties, the difference is in the font-family, which there are also duplicates:

     10         font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif;
      7         font-family: Tahoma, Arial, sans-serif;
      5         font-family: Arial, sans-serif;
      1         font-family: "Sukhumvit Set", "Helvetica Neue", helvetica, arial, sans-serif;
      1         font-family: "Libre Franklin", sans-serif;
      1         font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      1         font-family: "Arial Hebrew", Arial, sans-serif;
      1         font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", "Helvetica Neue", "Microsoft YaHei New", STHeiti Light, sans-serif;
      1         font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", "Microsoft YaHei New", STHeiti Light, sans-serif;
      1         font-family: -apple-system, BlinkMacSystemFont, "PingFang HK", "Helvetica Neue", "Microsoft YaHei New", STHeiti Light, sans-serif;
      1         font-family: -apple-system, BlinkMacSystemFont, "Hiragino Sans", Meiryo, "Helvetica Neue", sans-serif;
      1         font-family: "Apple SD Gothic Neo", "Malgun Gothic", "Nanum Gothic", Dotum, sans-serif;

So over two-thirds (22) of the font-family properties are duplicated. It turns out that :lang() allows for multiple languages to be specified (but see caveat below!), so the duplicated styles for 22 of the rules could be reduced to 3. If each rule is about 3.3KB, this would reduce 72 KB down to ~10KB.

So instead of there being 10 instances of:

body:lang(be), button:lang(be),
input:lang(be),
select:lang(be),
optgroup:lang(be),
textarea:lang(be), .author-description .author-link:lang(be),
.comment-metadata:lang(be),
.comment-reply-link:lang(be),
.comments-title:lang(be),
.comment-author .fn:lang(be),
.discussion-meta-info:lang(be),
.entry-meta:lang(be),
.entry-footer:lang(be),
.main-navigation:lang(be),
.no-comments:lang(be),
.not-found .page-title:lang(be),
.error-404 .page-title:lang(be),
.post-navigation .post-title:lang(be),
.page-links:lang(be),
.page-description:lang(be),
.pagination .nav-links:lang(be),
.sticky-post:lang(be),
.site-title:lang(be),
.site-info:lang(be),
#cancel-comment-reply-link:lang(be),
h1:lang(be),
h2:lang(be),
h3:lang(be),
h4:lang(be),
h5:lang(be),
h6:lang(be), .page-title:lang(be), blockquote cite:lang(be), table:lang(be), .button:lang(be),
input:lang(be)[type="button"],
input:lang(be)[type="reset"],
input:lang(be)[type="submit"], .comment-navigation .nav-previous:lang(be),
.comment-navigation .nav-next:lang(be), .comment-list .pingback .comment-body:lang(be),
.comment-list .trackback .comment-body:lang(be), .comment-list .pingback .comment-body .comment-edit-link:lang(be),
.comment-list .trackback .comment-body .comment-edit-link:lang(be), .comment-form .comment-notes:lang(be),
.comment-form label:lang(be), .widget_archive ul li:lang(be),
.widget_categories ul li:lang(be),
.widget_meta ul li:lang(be),
.widget_nav_menu ul li:lang(be),
.widget_pages ul li:lang(be),
.widget_recent_comments ul li:lang(be),
.widget_recent_entries ul li:lang(be),
.widget_rss ul li:lang(be), .widget_tag_cloud .tagcloud:lang(be), .widget_calendar .calendar_wrap .wp-calendar-nav:lang(be), .entry .entry-content .wp-block-button .wp-block-button__link:lang(be), .entry .entry-content .wp-block-archives li > a:lang(be),
.entry .entry-content .wp-block-categories li > a:lang(be),
.entry .entry-content .wp-block-latest-posts li > a:lang(be), .entry .entry-content .wp-block-latest-posts .wp-block-latest-posts__post-date:lang(be), .entry .entry-content .wp-block-verse:lang(be), .entry .entry-content .has-drop-cap:lang(be):not(:focus):first-letter, .entry .entry-content .wp-block-pullquote cite:lang(be), .entry .entry-content .wp-block-cover-image .wp-block-cover-image-text:lang(be),
.entry .entry-content .wp-block-cover-image .wp-block-cover-text:lang(be),
.entry .entry-content .wp-block-cover-image h2:lang(be),
.entry .entry-content .wp-block-cover .wp-block-cover-image-text:lang(be),
.entry .entry-content .wp-block-cover .wp-block-cover-text:lang(be),
.entry .entry-content .wp-block-cover h2:lang(be), .entry .entry-content .wp-block-audio figcaption:lang(be),
.entry .entry-content .wp-block-video figcaption:lang(be),
.entry .entry-content .wp-block-image figcaption:lang(be),
.entry .entry-content .wp-block-gallery .blocks-gallery-image figcaption:lang(be),
.entry .entry-content .wp-block-gallery .blocks-gallery-item figcaption:lang(be), .entry .entry-content .wp-block-file:lang(be), .entry .entry-content .wp-block-file .wp-block-file__button:lang(be), .entry .entry-content .wp-block-latest-comments .wp-block-latest-comments__comment-meta:lang(be), .wp-caption-text:lang(be), .gallery-caption:lang(be) {
        font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif;
}

We could instead have:

body:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), button:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
input:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
select:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
optgroup:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
textarea:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .author-description .author-link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-metadata:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-reply-link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comments-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-author .fn:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.discussion-meta-info:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry-meta:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry-footer:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.main-navigation:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.no-comments:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.not-found .page-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.error-404 .page-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.post-navigation .post-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.page-links:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.page-description:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.pagination .nav-links:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.sticky-post:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.site-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.site-info:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
#cancel-comment-reply-link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h1:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h2:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h3:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h4:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h5:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
h6:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .page-title:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), blockquote cite:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), table:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .button:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
input:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk)[type="button"],
input:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk)[type="reset"],
input:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk)[type="submit"], .comment-navigation .nav-previous:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-navigation .nav-next:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .comment-list .pingback .comment-body:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-list .trackback .comment-body:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .comment-list .pingback .comment-body .comment-edit-link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-list .trackback .comment-body .comment-edit-link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .comment-form .comment-notes:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.comment-form label:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .widget_archive ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_categories ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_meta ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_nav_menu ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_pages ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_recent_comments ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_recent_entries ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.widget_rss ul li:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .widget_tag_cloud .tagcloud:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .widget_calendar .calendar_wrap .wp-calendar-nav:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-button .wp-block-button__link:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-archives li > a:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-categories li > a:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-latest-posts li > a:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-latest-posts .wp-block-latest-posts__post-date:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-verse:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .has-drop-cap:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk):not(:focus):first-letter, .entry .entry-content .wp-block-pullquote cite:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-cover-image .wp-block-cover-image-text:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-cover-image .wp-block-cover-text:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-cover-image h2:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-cover .wp-block-cover-image-text:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-cover .wp-block-cover-text:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-cover h2:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-audio figcaption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-video figcaption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-image figcaption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-gallery .blocks-gallery-image figcaption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk),
.entry .entry-content .wp-block-gallery .blocks-gallery-item figcaption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-file:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-file .wp-block-file__button:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .entry .entry-content .wp-block-latest-comments .wp-block-latest-comments__comment-meta:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .wp-caption-text:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk), .gallery-caption:lang(be,bg,kk,mk,mn,ru,sah,sr,tt,uk) {
    font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif;
}

However, this is currently only supported by Firefox. But, there is another alternative which we could refactor yet further using :is() to combine the selectors and work around the lack support for multiple languages in :lang():

:is(
    body, button,
    input,
    select,
    optgroup,
    textarea, .author-description .author-link,
    .comment-metadata,
    .comment-reply-link,
    .comments-title,
    .comment-author .fn,
    .discussion-meta-info,
    .entry-meta,
    .entry-footer,
    .main-navigation,
    .no-comments,
    .not-found .page-title,
    .error-404 .page-title,
    .post-navigation .post-title,
    .page-links,
    .page-description,
    .pagination .nav-links,
    .sticky-post,
    .site-title,
    .site-info,
    #cancel-comment-reply-link,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6, .page-title, blockquote cite, table, .button,
    input[type="button"],
    input[type="reset"],
    input[type="submit"], .comment-navigation .nav-previous,
    .comment-navigation .nav-next, .comment-list .pingback .comment-body,
    .comment-list .trackback .comment-body, .comment-list .pingback .comment-body .comment-edit-link,
    .comment-list .trackback .comment-body .comment-edit-link, .comment-form .comment-notes,
    .comment-form label, .widget_archive ul li,
    .widget_categories ul li,
    .widget_meta ul li,
    .widget_nav_menu ul li,
    .widget_pages ul li,
    .widget_recent_comments ul li,
    .widget_recent_entries ul li,
    .widget_rss ul li, .widget_tag_cloud .tagcloud, .widget_calendar .calendar_wrap .wp-calendar-nav, .entry .entry-content .wp-block-button .wp-block-button__link, .entry .entry-content .wp-block-archives li > a,
    .entry .entry-content .wp-block-categories li > a,
    .entry .entry-content .wp-block-latest-posts li > a, .entry .entry-content .wp-block-latest-posts .wp-block-latest-posts__post-date, .entry .entry-content .wp-block-verse, .entry .entry-content .has-drop-cap:not(:focus):first-letter, .entry .entry-content .wp-block-pullquote cite, .entry .entry-content .wp-block-cover-image .wp-block-cover-image-text,
    .entry .entry-content .wp-block-cover-image .wp-block-cover-text,
    .entry .entry-content .wp-block-cover-image h2,
    .entry .entry-content .wp-block-cover .wp-block-cover-image-text,
    .entry .entry-content .wp-block-cover .wp-block-cover-text,
    .entry .entry-content .wp-block-cover h2, .entry .entry-content .wp-block-audio figcaption,
    .entry .entry-content .wp-block-video figcaption,
    .entry .entry-content .wp-block-image figcaption,
    .entry .entry-content .wp-block-gallery .blocks-gallery-image figcaption,
    .entry .entry-content .wp-block-gallery .blocks-gallery-item figcaption, .entry .entry-content .wp-block-file, .entry .entry-content .wp-block-file .wp-block-file__button, .entry .entry-content .wp-block-latest-comments .wp-block-latest-comments__comment-meta, .wp-caption-text, .gallery-caption
):is(
    :lang(be),
    :lang(bg),
    :lang(kk),
    :lang(mk),
    :lang(mn),
    :lang(ru),
    :lang(sah),
    :lang(sr),
    :lang(tt),
    :lang(uk)
) {
    font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif;
}

This is only 2.5 KB minified. Plus it's way easier to read, and :is() supported by all browsers supported by WordPress.

Last edited 3 months ago by westonruter (previous) (diff)

@sabernhardt
2 months ago

groups similar font rules with :is(), moves or reformats comments that do not fit and/or help much in final stylesheet, removes WOFF

#15 follow-up: @sabernhardt
2 months ago

  • Keywords has-patch added; needs-patch removed

I'm wary of increasing specificity of element selectors by grouping them with class and/or id selectors in :is(). In this case, it might only annoy a few people who took the effort to override those font styles (instead of replacing the stylesheet), but it would be a problem with a property such as color. Besides, I do not know how to group the list of selectors inside :is() with Sass.

I was able to group the similar :lang() selectors, and I removed the locales from the language codes.

  • That results in 12 rulesets instead of 31.
  • 6 of them are identical to what they have been.
  • Hebrew and Korean would not include their locales but are otherwise identical to the current CSS.

The patch could reduce style.css by about 50KB with low risk. 172KB still would be larger than any other Core theme's stylesheet, but it's a big improvement.

For the comments that are printed out of context, I was able to move some valuable comments to a better position (instead of reformatting them to show only in Sass).

#16 in reply to: ↑ 15 @westonruter
2 months ago

Replying to sabernhardt:

I'm wary of increasing specificity of element selectors by grouping them with class and/or id selectors in :is().

This is a great point I hadn't considered. I wish that :is() would only carry the specificity of the inner selector that actually matched, not the specificity of all the contained selectors.

Test case: https://codepen.io/westonruter/pen/eYwvPLj?editors=1100

In this case, could :where() be used instead? It specifically has a specificity of zero. This was leveraged recently in Gutenberg to facilitate overrides. So the generated CSS could rather be:

:where(
    body, button,
    input,
    select,
    optgroup,
    textarea, .author-description .author-link,
    .comment-metadata,
    .comment-reply-link,
    .comments-title,
    .comment-author .fn,
    .discussion-meta-info,
    .entry-meta,
    .entry-footer,
    .main-navigation,
    .no-comments,
    .not-found .page-title,
    .error-404 .page-title,
    .post-navigation .post-title,
    .page-links,
    .page-description,
    .pagination .nav-links,
    .sticky-post,
    .site-title,
    .site-info,
    #cancel-comment-reply-link,
    h1,
    h2,
    h3,
    h4,
    h5,
    h6, .page-title, blockquote cite, table, .button,
    input[type="button"],
    input[type="reset"],
    input[type="submit"], .comment-navigation .nav-previous,
    .comment-navigation .nav-next, .comment-list .pingback .comment-body,
    .comment-list .trackback .comment-body, .comment-list .pingback .comment-body .comment-edit-link,
    .comment-list .trackback .comment-body .comment-edit-link, .comment-form .comment-notes,
    .comment-form label, .widget_archive ul li,
    .widget_categories ul li,
    .widget_meta ul li,
    .widget_nav_menu ul li,
    .widget_pages ul li,
    .widget_recent_comments ul li,
    .widget_recent_entries ul li,
    .widget_rss ul li, .widget_tag_cloud .tagcloud, .widget_calendar .calendar_wrap .wp-calendar-nav, .entry .entry-content .wp-block-button .wp-block-button__link, .entry .entry-content .wp-block-archives li > a,
    .entry .entry-content .wp-block-categories li > a,
    .entry .entry-content .wp-block-latest-posts li > a, .entry .entry-content .wp-block-latest-posts .wp-block-latest-posts__post-date, .entry .entry-content .wp-block-verse, .entry .entry-content .has-drop-cap:not(:focus):first-letter, .entry .entry-content .wp-block-pullquote cite, .entry .entry-content .wp-block-cover-image .wp-block-cover-image-text,
    .entry .entry-content .wp-block-cover-image .wp-block-cover-text,
    .entry .entry-content .wp-block-cover-image h2,
    .entry .entry-content .wp-block-cover .wp-block-cover-image-text,
    .entry .entry-content .wp-block-cover .wp-block-cover-text,
    .entry .entry-content .wp-block-cover h2, .entry .entry-content .wp-block-audio figcaption,
    .entry .entry-content .wp-block-video figcaption,
    .entry .entry-content .wp-block-image figcaption,
    .entry .entry-content .wp-block-gallery .blocks-gallery-image figcaption,
    .entry .entry-content .wp-block-gallery .blocks-gallery-item figcaption, .entry .entry-content .wp-block-file, .entry .entry-content .wp-block-file .wp-block-file__button, .entry .entry-content .wp-block-latest-comments .wp-block-latest-comments__comment-meta, .wp-caption-text, .gallery-caption
):where(
    :lang(be),
    :lang(bg),
    :lang(kk),
    :lang(mk),
    :lang(mn),
    :lang(ru),
    :lang(sah),
    :lang(sr),
    :lang(tt),
    :lang(uk)
) {
    font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif;
}

Test case: https://codepen.io/westonruter/pen/eYwvPQL?editors=1100

#17 @sabernhardt
2 months ago

You may have meant the same thing by "all" selectors, but :is() matches the highest specificity of any selector in the list.

Using :where() for both sets of selectors would make these font overrides ineffective. Even the body element's font would remain the theme's serif selection instead of the fonts chosen for each language.

Combining :where(*):is(:lang()) would have a specificity of 0-1-0, which is not high enough for all matching elements.

  • Anything that matches the 14 element-only selectors would show in the language's font.
  • Located at the beginning of the stylesheet, the non-latin font rulesets could not override 17 single-class selectors.
  • The overrides would not replace the font for 50 selectors with a specificity higher than one class, regardless of where these rules are.
Note: See TracTickets for help on using tickets.