Skip to content

Replace hardcoded breakpoints in front-end CSS with more modular CSS #35848

Open

Description

@cr0ybot

What problem does this address?

Hardcoded screen width media queries like the 600px breakpoint for the core/columns block poses a not-insignificant problem for theme developers. We either have to work with that specific breakpoint, integrating it with our design system (even if we don't agree with pixel-based breakpoints #16911), completely remove core Gutenberg front-end styles, or otherwise hack around the CSS which no one enjoys doing. Some of these styles are particularly egregious to work around because they involve !important declarations to override inline styles.

What is your proposed solution?

I recently submitted a proposed solution using CSS custom properties #35808 and then immediately found out that this is not currently possible: https://bholmes.dev/blog/alternative-to-css-variable-media-queries/.

There is also no hook or other customization vector available to change the breakpoints. #19460

Regardless, I don't think that standard back-end breakpoints should cross over into front-end styles.

Instead, there are ways to write CSS for responsive layouts that do not rely on external breakpoints, but rather internal sizes. A good example is the "Switcher" layout from Every Layout. This approach, combined with some contextual CSS custom properties, would allow for easier manipulation of minimum-width of columns before they break into a single column, for example.

The challenge to overcome here is that this might not be a very backwards-compatible solution. Some themes out there in the wild are probably depending on hacky CSS workarounds to change the breakpoint of certain blocks, for example. However, I feel like this would be a more sustainable approach for future overrideability.

Here are the blocks I found that include hardcoded breakpoints:

  1. columns
  2. gallery
  3. latest-posts
  4. media-text
  5. navigation
  6. post-template
  7. rss

This search URL should probably find all of them: https://github.com/search?q=%24break-small+repo%3AWordPress%2Fgutenberg++path%3A%2Fpackages%2Fblock-library%2F+filename%3Astyle.scss&type=Code&ref=advsearch&l=&l=

Other issues that have attempted to start conversations similar to this:

Related PRs:

Activity

  1. added
    [Type] FeatureNew feature to highlight in changelogs.
    CSS StylingRelated to editor and front end styles, CSS-specific issues.
    on Oct 25, 2021
  2. DeoThemes commented on Oct 31, 2021

    @DeoThemes

    That's definitely an important feature. 600px is very small for mobile screens, most of the frameworks collapse at ~700-1000px. It makes navigation looks messy if there are many links, they simply don't fit.

  3. cr0ybot commented on Nov 5, 2021

    @cr0ybot
    ContributorAuthor

    @DeoThemes I have found in general that columns not collapsing until <600px results in some pretty extreme content squashing for more than 2 columns.

    I'd like to also point out that using px units in media queries is just all-around not great. Different browsers (particularly Safari) handle px value breakpoints at different sizes depending on browser zoom and user font size. See https://zellwk.com/blog/media-query-units/

  4. kraftner commented on Nov 25, 2021

    @kraftner

    Related: #12299 including a possible workaround covered in #12299 (comment)

  5. palmsout commented on Dec 3, 2021

    @palmsout

    @cr0ybot I agree. There's a real need for grid layouts in the query loop block, and elsewhere, to respond at user defined breakpoints, and especially a need for columns to reduce responsively with screen size (beyond just going from, for instance, 3 columns above 600px to 1 column under 600px). Query loop block needs the option to define at least a middle ground option between say 600 & 100opx, but ideally at user defined points.

  6. Azragh commented on Jan 10, 2022

    @Azragh
  7. cr0ybot commented on Jan 13, 2022

    @cr0ybot
    ContributorAuthor

    Comparing the browserlist config for this project against Caniuse flexbox-gap, it looks like we should be safe swapping the margin stuff that ends up getting a little too specific to easily override with gap.

    It looks like this effort is already underway with the block gap feature having been merged in: #33991

    However, the underlying spacing in columns and other places is still being accomplished via margins instead of the gap property, though it seems like it's understood that this is the next step. Is there some kind of theme support proposal to opt themes into using gap instead of margins? Obviously changing the styles so dramatically would likely break backwards compatibility.

    UPDATE: The core columns block uses gap now! #37436

    The part that worries me most is that a columns block that breaks without a breakpoint would probably need to have its columns' flex-basis based on absolute values instead of relative percentages as they are currently done. This is a big change to how the columns block works currently. However, if column widths were based on an absolute size, they would fit side-by-side until they don't anymore, without the need for a hardcoded breakpoint.

  8. cr0ybot commented on Jan 20, 2022

    @cr0ybot
    ContributorAuthor

    Related: #12299 including a possible workaround covered in #12299 (comment)

    I finally got around to reading your blog post linked in that comment: https://kraftner.com/en/blog/building-your-own-wordpress-core-block-css/

    Completely replacing the core block stylesheet is a workaround, but you end up in a situation that is very fragile. As WordPress/Gutenberg update with new/updated blocks, the replacement stylesheet is stuck at the old version.

    If it were possible to override individual block styles, I'd feel that is a more tenable solution. It looks like the should_load_separate_core_block_assets hook might provide a possible way forward for that? We should be able to override the stylesheet enqueue via the slug, though combined stylesheets are still loaded in the editor. I'm going to mess around with this to see if it's feasible.

  9. kraftner commented on Jan 20, 2022

    @kraftner

    @cr0ybot I 100% agree that this is a terrible workaround which I'd love to get rid of. I see my blog post 50% as showing a workaround and 50% as an illustration of how terrible the current situation is and why it needs fixing. 😉

  10. LukaszJaro commented on Feb 4, 2022

    @LukaszJaro

    Also by using grid it would reduce the amount of CSS shipped most likely, especially if media queries were eliminated. I recently ran into issue trying to override the 600px media query and had to use !Important.

    I still use flexbox for items but grid is best for container type of layouts like columns.

  11. chthonic-ds commented on Feb 5, 2022

    @chthonic-ds
    Contributor

    Completely replacing the core block stylesheet is a workaround, but you end up in a situation that is very fragile.

    This is something I've experimented with since WP 5.0 was released and it's been a lot less fragile than I initially worried it would be.

    If it were possible to override individual block styles, I'd feel that is a more tenable solution. It looks like the should_load_separate_core_block_assets hook might provide a possible way forward for that?

    I've been using something as simple as the following to achieve this:

    add_filter( 'should_load_separate_core_block_assets', '__return_true' );
    
    function use_custom_styles() {
      $blocks = array(
        'columns',
      );
    
      foreach ( $blocks as $block) {
        wp_deregister_style( 'wp-block-' . $block );
        wp_register_style( 'wp-block-' . $block, 'path/to/custom/block.css' );
      }
    }
    
    add_action( 'wp_enqueue_scripts', 'use_custom_styles' );
    
  12. RatzeR commented on Jun 10, 2022

    @RatzeR

    For some blocks, for example the navigation block, it would be great, if it would be possible to change the breakpoint where the block uses the mobile / desktop navigation.
    And as it seems to be the goal to have everything configurable, it should be possible to change the breakpoint via the block.json or theme.json file.

  13. fabiankaegy commented on Nov 9, 2022

    @fabiankaegy
    Member

    I also think that adding a way for themes to define the breakpoints would be very useful. This setting could be exposed via theme.json and even made available in some advanced settings in the site editor.

    Users and developers already have the ability to change the contentWidth and wideWidth in the layout section.

    Either these breakpoints could be set as part of the layout or as part of a new breakpoints key.

    These here are the breakpoints that Gutenberg currently uses in its scss:

    // Most used breakpoints
    $break-huge: 1440px;
    $break-wide: 1280px;
    $break-xlarge: 1080px;
    $break-large: 960px; // admin sidebar auto folds
    $break-medium: 782px; // adminbar goes big
    $break-small: 600px;
    $break-mobile: 480px;
    $break-zoomed-in: 280px;

    And looking at the block-library style.css files there are only a two breakpoints that actually get used in the frontend styles:

    small

    medium

    So I think those are the only two that would need to get exposed in theme.json by default. But ideally the system could be flexible enough so themes could use this to also define their own breakpoints on top of the core ones.

  14. aurooba commented on Feb 4, 2023

    @aurooba
    Member

    Fully echo what @fabiankaegy said. theme.json should have the capability to override existing breakpoints and/or add more. I understand the arguments of intrinsic layouts, but that's simply not a realistic approach for everything yet.

  15. 7 remaining items

  16. colorful-tones commented on Mar 2, 2024

    @colorful-tones
    Member

    I forgot CSS variables do not work in media query declarations. 🤦‍♂️

  17. colorful-tones commented on Apr 19, 2024

    @colorful-tones
    Member

    Here is a solution (more of a workaround).

    https://gist.github.com/colorful-tones/22da9a7f6a1f5867903e5eff826567e1

    It is nothing new and I think it is a derivative of @kraftner’s article https://kraftner.com/en/blog/building-your-own-wordpress-core-block-css/

    I think it could be worth exploring extending ʼtheme.jsonʼ to allow for these breakpoints.

  18. kraftner commented on Apr 30, 2024

    @kraftner

    @colorful-tones If I read this right what you're doing is adding CSS on top. My approach is about replacing it so you do not constantly have to fight against core styles.

    Having said that my blog post is quite old and dated by now. While still not great a more modern approach might be able to combine https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-support/#disabling-base-layout-styles and what was proposed by @cr0ybot above.

    I wish I'd have the time to write a follow up post to the one you linked with these approaches. But doesn't look like it right now.

    Even if - still these are all just workarounds to the core issue: Breakpoints are hardcoded. And to change them the CSS custom property based approach for anything else from theme.json doesn't work here since media queries can't use custom properties.

  19. added
    [Focus] Blocks AdoptionFor issues that directly impact the ability to adopt features of Gutenberg.
    on May 8, 2024
  20. alperta commented on Sep 12, 2024

    @alperta

    +1 for breakpoint setup in theme.json. Long menus look really bad at 600px (and up to 800px most of the time).

  21. jnz31 commented on Sep 17, 2024

    @jnz31

    +1

  22. coreyworrell commented on Oct 23, 2024

    @coreyworrell
    Contributor

    This feels like a critical need, as WordPress is still using pixel breakpoints, which is not responsive or accessible to the user's browser default font size. So as text size increases, pixel breakpoints happen way too early/late. And having these configurable in the theme, and even per block, would be great.

  23. hagege commented on Oct 23, 2024

    @hagege

    +1 for breakpoint overrides available via theme.json.

  24. magl88 commented on Nov 6, 2024

    @magl88

    I don't understand why such an important thing wasn't done right away and is being postponed.
    I often come across designs with different variations of breakpoints
    and more than just mobile and tablet and desktop.
    And what about TV?

    Sometimes I need even 5 breakpoints

    OR do I need to set the sizes via the css clamp() property

  25. vollyimnetz commented on Jan 21, 2025

    @vollyimnetz

    Totally agree, some more controll is needed. One way to have at least some controll for developers would be a filter in the function WP_Styles->print_inline_style

    Something like the following would be totaly suitable for most cases:

    // in WP_Styles->print_inline_style
    $output = apply_filters('print-inline-style', $handle, $output);
    // Attention currently not possible to use this!
    

    In this way someone could replace the current default value of 782px with something to there own like. This is a generall purpose approach (as one can override any inline-style).

  26. vollyimnetz commented on Jan 28, 2025

    @vollyimnetz

    The following code uses the existing columns inline style (from wp-includes/blocks/columns/style.css) and changes the breakpoints to new values.

    add_action('wp_enqueue_scripts', function() {
    	//remove existing css-output of the columns-block
    	wp_dequeue_style( 'wp-block-columns' );
    }, 10 );
    
    /**
     * will add custom columns block css output based on the original style file
     */
    add_action('wp_head', function() {
    	$oldBreakpoint = 782;
    	$newBreakpoint = 760;
    
    	$search = [
    		$oldBreakpoint.'px',
    		($oldBreakpoint-1).'px',
    	];
    	$replace = [
    		$newBreakpoint.'px',
    		($newBreakpoint-1).'px',
    	];
    
    	$pathToBlockCss = 'wp-includes/blocks/columns/style.css';
    	$cssFileContent = file_get_contents(ABSPATH.$pathToBlockCss);
    
    		//modify the existing css content
    	$cssFileContent = str_replace($search, $replace, $cssFileContent);
    	$cssFileContent.= 'body { border-left: 50px solid green; }';//any additional CSS Code --> see if its working REMOVE LATER
    
    	echo '<style id="my-columns-inline-css">'.$cssFileContent.'</style>';
    });
    

    Note: you may use a different style.css if you are on an rtl layout.

  27. gabbsmo commented on Sep 17, 2025

    @gabbsmo

    theme.json property is nice, but a CSS variable or PHP hook would be very useful for legacy themes as well.

  28. kraftner commented on Sep 17, 2025

    @kraftner

    a CSS variable […] would be very useful for legacy themes

    @gabbsmo Unfortunately that is technically not possible on CSS/browser level.

  29. gabbsmo commented on Sep 17, 2025

    @gabbsmo

    Thanks. A PHP filter hook then so that legacy themes are not left out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    CSS StylingRelated to editor and front end styles, CSS-specific issues.[Focus] Blocks AdoptionFor issues that directly impact the ability to adopt features of Gutenberg.[Type] FeatureNew feature to highlight in changelogs.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions