Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Style directives #42

Merged
merged 6 commits into from
Nov 29, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 />
```