linkedin / linkedin/css-blocks
Rules on universal selector (*) and combinors prevent using the 'lobotomised owl' selector (:scope > * + *)
- Dominant language
- TypeScript
- Stars
- 6.3k
- Forks
- 154
- PR merge metrics
- No merged PRs in 30d
Description
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](https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/)). 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.
```css
/* 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.](https://every-layout.dev/layouts/stack/))
```jsx
CSS is awesome
Foo
Foo
Foo
```
```css
/* 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.
Contributor guide
Research direction
Start by reviewing CSS Blocks' restrictions on universal selectors and combinators, then compare the requested `:scope > * + *` behavior with the Stack and Flex use cases shown here. Done means determining whether the selector can be supported or documenting an equivalent CSS Blocks approach for these layout components.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- css
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100