linkedin / linkedin/css-blocks

Styling Scope State Dependent Descendant DOM

Open
#40 1 comment 0 reactions 0 assignees View on GitHub
@css-blocks/core enhancement under consideration
Dominant language
TypeScript
Stars
6.3k
Forks
154
PR merge metrics
No merged PRs in 30d

Description

## Problem
Consider:
A nav design where a link, containing an icon and a label, are red and blue respectively at rest. When any part of the link is hovered, they both the link and the label should become green:

```html



Label

```

```css
.root {
background-color: black;
}
.link {
color: red;
}
.link:hover {
color: green;
}
.icon {
color: currentColor;
}
.label {
color: blue;
}

/* This is not currently allowed by css-blocks */
.link:hover .label {
color: currentColor;
}
```

## Proposals
There are two (2) proposals for how to accommodate for this use case:

---

**Proposal 1**: Require developer to make a *new* block just for the nav link. `.link` would become that block's `.root`, and the `:hover` state on the root would become the new context selector for `.label`. Blocks allow root states as context selectors and the only change require to make this work is to treat pseudo-selectors on the root class as states.

---

**Proposal 2**: Loosen restrictions on Block syntax to allow ClassStates as context selectors, enabling developers to write selectors like `.link:hover .label`. This syntax relaxation will output the same exact code as creating a new block, but not require the end developer to jump through hoops for simple features like customizing hover effects. Using bare Classes as context selectors would still be disallowed.

By only allowing compound selectors that terminate in a state as context selectors, we still encourage simple, flat style construction, but acknowledge that internal state (read: not root state) may have an effect on other elements within the component.

---

**Proposal 1** upholds the current mental model of css-blocks where root states are the only context selectors allowed by the framework; simplifying development, vastly limiting selector complexity, and preventing CSS specificity foot-guns. Developers are forced to engineer very flat style hierarchies, reducing style complexity and maximizing optimization benefits.

**Proposal 2**, in most cases, will result in the same exact CSS output as Proposal 1, without the developer overhead of creating a whole new block and wiring up a block-reference just for the sake of creating a very common hover style pattern.

**Proposal 2** has the added benefit of enabling _**very common**_ css patterns that are currently impossible with CSS Blocks, described in more detail below.

## Drawbacks

### Proposal 1
This issue raises concerns about some exceptionally common CSS patterns that are currently impossible with css-blocks as is. Proposal 1 does nothing to fix these concerns. Consider a custom checkbox component using the _**only**_ method in CSS for creating styled check boxes:

```jsx
import checkbox from "./styles.css";

return (


Click me!

);
```
```scss
// styles.css
.root {
...
}
.input {
opacity: 0;
pointer-events: none;
}
.label {
background-color: red;
}
.input:checked + .label {
background-color: green;
}
```
The above is not currently possible with css-blocks and no combination of new block files, global states, or inheritance make it work, even after treat pseudo-selectors on the root class as states. (@chriseppstein, please confirm?)

### Proposal 2
Proposal 2 has the added benefit of enabling very common css patterns that are currently impossible with CSS Blocks, but with this comes the worry that developers can abuse this behavior, resulting in less-intuitive CSS and impacting optimization. For example, more freely using internal state to style components with sibling selectors instead of using root state:
```css
.an-item[state|active] ~ .following-itmes {
...
}
```
These less-than-ideal selectors can have a non-trivial impact on optimization.

However, the argument can be made that when developers use sibling selectors they do so with intention and disallowing their use can drastically limit the styles we can compose with CSS, as shown above.

Contributor guide

Open the contributing guide

Research direction

No source file, test, or entry point is named. Compare Proposal 1 with Proposal 2, then determine which selector forms should be supported and how the optimization concerns are resolved. The issue is done when the project records a decided approach and implementation scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
css, typescript
Domain
frontend, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.