Skip to content

Commit

Permalink
Merge pull request #42 from plmrry/style-directives
Browse files Browse the repository at this point in the history
Style directives
  • Loading branch information
Rich-Harris authored Nov 29, 2021
2 parents 36f2290 + af01272 commit ca46eb3
Showing 1 changed file with 129 additions and 0 deletions.
129 changes: 129 additions & 0 deletions text/0000-style-directives.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
- Start Date: 2020-12-09
- RFC PR: (leave this empty)
- Svelte Issue: (leave this empty)

# Style Directive

## Summary

Add a `style:` directive:

```svelte
<div style:position="absolute" style:left="67px" />
```

## Motivation

Currently, when inline style attributes need to be set based on multiple variables, the construction of a style attribute string is left to the developer.

Constructing these attribute strings can become somewhat clumsy.

For example:

```svelte
<div
style="
position: {position};
{position === 'absolute' ? 'top: 20px;' : ''}
{pointerEvents === false ? 'pointer-events:none;' : ''}
"
/>
```

It would be useful — and often less error-prone — to be able to set multiple inline styles without having to construct the attribute string:

```svelte
<div
style:position="absolute"
style:top={position === "absolute" ? "20px" : null}
style:pointer-events={pointerEvents ? null : "none"}
/>
```

## Detailed design

Style directives would take the form `style:property="value"` where `property` is a CSS property and `value` is a CSS property value.

### Shorthand

A shorthand form could also exist when a variable name and CSS property name match:

```svelte
<script>
const left = "234px";
</script>
<div style:left />
```

### Conflicting Styles

One question surrounding this approach how to combine style directives with style attribures that have conflicting properties.

Consider the example:

```svelte
<div style="position: absolute; left: 40px;" style:left="50px" />
```

What would be the value of this element's `left` property?

It seems there are three options available:

1. Conflicting CSS properties in style directives are not allowed, and a compiler error is thrown.
2. The style attribute takes precedence.
3. The style directive takes precedence.

The third option seems like the most reasonable, and most closely matches the behavior of the `class:` directive.

For example, class directives take precedence over class attribute strings:

```svelte
<div class="foo bar" class:bar={false}>
My class is "foo" and not "foo bar"
</div>
```

### CSS Variables

These directives could also contain CSS variables:

```svelte
<div style:--border-color="saddleBrown" />
```

## How we teach this

This is pretty similar to the `class:` directive, except that a CSS value is used instead of a boolean.

## Drawbacks

As with any feature, this would add some complexity to the codebase, and add a bit of learning curve, although the impact seems minimal.

We may want to discourage the construction of complex inline styles based on variables, and encourage the use of CSS variables instead.
Of course, dynamic CSS variables would also need to be passed into a style attribute.

## Alternatives

React uses a style object:

```jsx
<div style={{ marginLeft: "30px" }} />
```

We could instead mimic React and allow this sort of object to be passed to an element's `style` attribute.

## Unresolved questions

### Camel Case Property Names?

We could also allow for the use of camel case property names.

This would make using variable names that match CSS properties a bit easier:

```svelte
<script>
const marginLeft = "20px";
</script>
<div style:marginLeft />
```

0 comments on commit ca46eb3

Please sign in to comment.