Skip to content

Rules on universal selector (*) and combinors prevent using the 'lobotomised owl' selector (:scope > * + *) #508

@JoshTumath

Description

@JoshTumath

I love the concept of CSS Blocks and would love to use it in my team's design system. However, it expressly forbids the use of a selector like :scope > * + * (known to some people as the lobotomised owl selector). I want to present our use-case to you and see what you think! Maybe this is a convincing argument for CSS Blocks to support the owl selector, or maybe there's an equivalent alternative way of doing the same thing in CSS Blocks that solves the same problem.

Use case: layout components

In a design system, you want components to be self contained and not have to worry about how they're laid out. We have a rule in our design system called 'No outer margins'. It should be possible to use a component anywhere without having to worry about where it will be used. If the component has a margin on the outside, it may have a gap around it where you haven't intended it.

So how do you set gaps and margins between components? In our design system, that's a the parent component's responsibility to compose them together. We call the components that have this responsibility 'layout components'.

For example, a layout component called Grid would use CSS Grid to lay out its children. And the gap property would set the gap between components. I wouldn't need to go outside of the scope of the Grid component to set the gap between child components because of the way CSS Grid works; that can be done from the parent.

/* Grid */
:scope {
  display: grid;
  gap: 1rem;
}

However, if I don't need to use a grid layout - if I just want a stack of paragraphs and images in an article to be laid out one-below-the-other - I just need the default CSS flow layout. So I need to use a margin to set a space/gap between components. That's where the owl selector comes in. I can create a layout component called Stack and it will set a gap between its children; I don't need to worry about what components those children are. (The Book 'Every Layout' makes a great case for the owl selector when explaining the Stack layout.)

<Stack>
  <h1>CSS is awesome</h1>
  <p>Foo</p>
  <p>Foo</p>
  <p>Foo</p>
</Stack>
/* Stack */
:scope {
  display: block;
}

:scope > * + * {
  margin-top: 1rem;
}

It's a similar problem if you're using CSS Flex to create a layout, and you need to add the flex property to the children to set varying flex amounts.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions