Styling the separator block in five attempts

The “Separator” block in WordPress is fairly simple and semantic. I mean, it’s just an <hr> element with some styles, and maybe some classes to achieve those styles. In terms of the promise of Gutenberg (where everything in HTML becomes a simple block/component), it’s ideal.

On a recent project, I needed to change the default color of the Separator block. It’s basically just overriding a border-color , how hard can that be? That said, I’m not too familiar with the nitty-gritty of how the block editor styles HTML elements, so it left me wondering- where do we start?

TL;DR – You can just skip to the right answer if you want.

Attempt 1: Regular ol CSS.

In my main theme’s stylesheet, I added something along the lines of this:

hr { border-color: gray; }Code language: CSS (css)

(It wasn’t actually “gray” but let’s keep it simple.) So, did it work? Nope. WordPress actually adds its own styles, and it does it based on the class .wp-block-separator not the <hr>. So WordPress core overrules my default styles for the element.

Attempt 2. Regular ol’ scoped CSS.

Ok, what if I target the .wp-block-separator instead of the element, like WordPress does? Unfortunately, this doesn’t work either. Because WordPress can inline a lot of the smaller stylesheets for blocks (and an <hr> doesn’t need a huge stylesheet), their inline styles take precedent over my stylesheet.

.wp-block-separator { border-color: gray; }Code language: CSS (css)

Inlining styles is great, but it does add an extra level of importance that may conflict with your own styles.

Quick Aside: As I’m writing this up, I realize I could’ve also tried combining the element with the class selector like this:

hr.wp-block-separator { border-color: gray; }Code language: CSS (css)

This actually would’ve worked, because it would’ve taken a higher priority than the inline stylesheet. That said, it may have ended up being too specific and conflicted with the block editor later on.

In any case, if the block editor is inlining styles, why not work with it instead of against it. That takes us to attempt three.

Attempt 3. Theme.json “Elements”

Can I define the default color in my theme.json file? An <hr> is an “element”, and theme.json has an “elements” section, so I’ll check there.

{  
  "styles": {
    "elements": {
      "hr": {
        "border": {
          "color": "gray"
        }
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

No luck. The thing is, you can set the default styles for a few elements there- headings, <cite>, nothing too crazy- but you can’t just name any old HTML element and have it spit out styles for you. So the example above is just not readable by the block editor.

Attempt 4. A block-specific stylesheet.

With the block editor, you can use the wp_enqueue_block_style() function to add your own stylesheet to any block. This is super handy when you create your own block variations or block styles and need to enqueue an extra stylesheet for a particular block.

The theme I’m using has a great build process and helps me register these block-specific stylesheets, so I create my stylesheet for the Separator block.

This actually works! In the footer of my page, I can see my stylesheet being added right below the core stylesheet:

A screenshot of the source of my site. We can see the inline style element for core separator block, and then a second inline style element with my custom override.

This works! But this just doesn’t feel right. Why am I loading two separate style tags for something as simple as an <hr> element? Then it hits me.

I’m honestly surprised it took me this long to get here. I’m trying to define the default styling for a block- not an HTML element. That’s exactly what theme.json is for. I guess… in my mind I was still thinking of it as HTML.

5. Theme.json “Blocks”

When you want a default style for your blocks, use theme.json. Of course.

Here’s a snippet:

{  
  "styles": {
    "blocks": {
      "core/separator": {
        "border": {
          "color": "gray"
        }
      }
    }
  }
}Code language: JSON / JSON with Comments (json)

This is probably the right way to do it. Maybe it’s just the years of classic WordPress thinking that make it so hard for me to go to the JSON before I go to my stylesheet. And thinking about things “block-first” instead of “semantic HTML-first”.

Postscript

I’ll be honest here, I still want to apply the color to my <hr> element in my stylesheet. So I’ll probably include this first attempt as well:

hr { border-color: gray; }Code language: CSS (css)

Why do I need to style the <hr> if I’m using the block editor anyway? I don’t know. It feels wrong to style the separator as a block but not also make sure some random silly HTML element doesn’t sneak in and mess up the design. If this extra line of CSS is wrong, I don’t want to be right.

Learn Modern WordPress Development

I’m sharing the best resources and tutorials for developers building in and on the block editor.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.