Skip to content

Commit 517ae81

Browse files
author
Rich Harris
committed
better class example
1 parent f9c9110 commit 517ae81

File tree

8 files changed

+284
-76
lines changed

8 files changed

+284
-76
lines changed

content/tutorial/03-advanced-svelte/06-classes/01-classes/README.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,27 @@
22
title: The class directive
33
---
44

5-
Like any other attribute, you can specify classes with a JavaScript attribute, seen here:
5+
Like any other attribute, you can specify classes with a JavaScript attribute. Here, we could add a `flipped` class to the card:
66

77
```svelte
88
/// file: App.svelte
99
<button
10-
class={current === 'foo' ? 'selected' : ''}
11-
on:click={() => current = 'foo'}
12-
>foo</button>
10+
class="card +++{flipped ? 'flipped' : ''}+++"
11+
on:click={() => flipped = !flipped}
12+
>
1313
```
1414

15-
This is such a common pattern in UI development that Svelte includes a special directive to simplify it:
15+
This works as expected — if you click on the card now, it'll flip.
16+
17+
We can make it nicer though. Adding or removing a class based on some condition is such a common pattern in UI development that Svelte includes a special directive to simplify it:
1618

1719
```svelte
1820
/// file: App.svelte
1921
<button
20-
+++class:selected={current === 'foo'}+++
21-
on:click={() => current = 'foo'}
22-
>foo</button>
22+
class="card"
23+
+++class:flipped={flipped}+++
24+
on:click={() => flipped = !flipped}
25+
>
2326
```
2427

25-
The `selected` class is added to the element whenever the value of the expression is truthy, and removed when it's falsy.
28+
This directive means 'add the `flipped` class whenever `flipped` is truthy'.
Lines changed: 84 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,92 @@
11
<script>
2-
let current = 'foo';
2+
let flipped = false;
33
</script>
44

5-
<button
6-
class={current === 'foo' ? 'selected' : ''}
7-
on:click={() => (current = 'foo')}>foo</button
8-
>
5+
<div class="container">
6+
Flip the card
7+
<button
8+
class="card"
9+
on:click={() => flipped = !flipped}
10+
>
11+
<div class="front">
12+
<span class="symbol">♠</span>
13+
</div>
14+
<div class="back">
15+
<div class="pattern"></div>
16+
</div>
17+
</button>
18+
</div>
919

10-
<button
11-
class={current === 'bar' ? 'selected' : ''}
12-
on:click={() => (current = 'bar')}>bar</button
13-
>
20+
<style>
21+
.container {
22+
display: flex;
23+
flex-direction: column;
24+
gap: 1em;
25+
height: 100%;
26+
align-items: center;
27+
justify-content: center;
28+
perspective: 100vh;
29+
}
1430
15-
<button
16-
class={current === 'baz' ? 'selected' : ''}
17-
on:click={() => (current = 'baz')}>baz</button
18-
>
31+
.card {
32+
position: relative;
33+
aspect-ratio: 2.5 / 3.5;
34+
font-size: min(1vh, 0.25rem);
35+
height: 80em;
36+
background: var(--bg-1);
37+
border-radius: 2em;
38+
transform: rotateY(180deg);
39+
transition: transform 0.4s;
40+
transform-style: preserve-3d;
41+
padding: 0;
42+
user-select: none;
43+
cursor: pointer;
44+
}
1945
20-
<style>
21-
.selected {
22-
background-color: #ff3e00;
23-
color: white;
46+
.card.flipped {
47+
transform: rotateY(0);
48+
}
49+
50+
.front, .back {
51+
display: flex;
52+
align-items: center;
53+
justify-content: center;
54+
position: absolute;
55+
width: 100%;
56+
height: 100%;
57+
left: 0;
58+
top: 0;
59+
backface-visibility: hidden;
60+
border-radius: 2em;
61+
border: 1px solid var(--fg-2);
62+
box-sizing: border-box;
63+
padding: 2em;
64+
}
65+
66+
.front {
67+
background: url(./svelte-logo.svg) no-repeat 5em 5em, url(./svelte-logo.svg) no-repeat calc(100% - 5em) calc(100% - 5em);
68+
background-size: 8em 8em, 8em 8em;
69+
}
70+
71+
.back {
72+
transform: rotateY(180deg);
73+
}
74+
75+
.symbol {
76+
font-size: 30em;
77+
color: var(--fg-1);
78+
}
79+
80+
.pattern {
81+
width: 100%;
82+
height: 100%;
83+
background-color: var(--bg-2);
84+
/* pattern from https://projects.verou.me/css3patterns/#marrakesh */
85+
background-image:
86+
radial-gradient(var(--bg-3) 0.9em, transparent 1em),
87+
repeating-radial-gradient(var(--bg-3) 0, var(--bg-3) 0.4em, transparent 0.5em, transparent 2em, var(--bg-3) 2.1em, var(--bg-3) 2.5em, transparent 2.6em, transparent 5em);
88+
background-size: 3em 3em, 9em 9em;
89+
background-position: 0 0;
90+
border-radius: 1em;
2491
}
2592
</style>
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 85 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,93 @@
11
<script>
2-
let current = 'foo';
2+
let flipped = false;
33
</script>
44

5-
<button
6-
class:selected={current === 'foo'}
7-
on:click={() => (current = 'foo')}>foo</button
8-
>
5+
<div class="container">
6+
Flip the card
7+
<button
8+
class="card"
9+
class:flipped={flipped}
10+
on:click={() => flipped = !flipped}
11+
>
12+
<div class="front">
13+
<span class="symbol">♠</span>
14+
</div>
15+
<div class="back">
16+
<div class="pattern"></div>
17+
</div>
18+
</button>
19+
</div>
920

10-
<button
11-
class:selected={current === 'bar'}
12-
on:click={() => (current = 'bar')}>bar</button
13-
>
21+
<style>
22+
.container {
23+
display: flex;
24+
flex-direction: column;
25+
gap: 1em;
26+
height: 100%;
27+
align-items: center;
28+
justify-content: center;
29+
perspective: 100vh;
30+
}
1431
15-
<button
16-
class:selected={current === 'baz'}
17-
on:click={() => (current = 'baz')}>baz</button
18-
>
32+
.card {
33+
position: relative;
34+
aspect-ratio: 2.5 / 3.5;
35+
font-size: min(1vh, 0.25rem);
36+
height: 80em;
37+
background: var(--bg-1);
38+
border-radius: 2em;
39+
transform: rotateY(180deg);
40+
transition: transform 0.4s;
41+
transform-style: preserve-3d;
42+
padding: 0;
43+
user-select: none;
44+
cursor: pointer;
45+
}
1946
20-
<style>
21-
.selected {
22-
background-color: #ff3e00;
23-
color: white;
47+
.card.flipped {
48+
transform: rotateY(0);
49+
}
50+
51+
.front, .back {
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
position: absolute;
56+
width: 100%;
57+
height: 100%;
58+
left: 0;
59+
top: 0;
60+
backface-visibility: hidden;
61+
border-radius: 2em;
62+
border: 1px solid var(--fg-2);
63+
box-sizing: border-box;
64+
padding: 2em;
65+
}
66+
67+
.front {
68+
background: url(./svelte-logo.svg) no-repeat 5em 5em, url(./svelte-logo.svg) no-repeat calc(100% - 5em) calc(100% - 5em);
69+
background-size: 8em 8em, 8em 8em;
70+
}
71+
72+
.back {
73+
transform: rotateY(180deg);
74+
}
75+
76+
.symbol {
77+
font-size: 30em;
78+
color: var(--fg-1);
79+
}
80+
81+
.pattern {
82+
width: 100%;
83+
height: 100%;
84+
background-color: var(--bg-2);
85+
/* pattern from https://projects.verou.me/css3patterns/#marrakesh */
86+
background-image:
87+
radial-gradient(var(--bg-3) 0.9em, transparent 1em),
88+
repeating-radial-gradient(var(--bg-3) 0, var(--bg-3) 0.4em, transparent 0.5em, transparent 2em, var(--bg-3) 2.1em, var(--bg-3) 2.5em, transparent 2.6em, transparent 5em);
89+
background-size: 3em 3em, 9em 9em;
90+
background-position: 0 0;
91+
border-radius: 1em;
2492
}
2593
</style>

content/tutorial/03-advanced-svelte/06-classes/02-class-shorthand/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,20 @@ Often, the name of the class will be the same as the name of the value it depend
66

77
```svelte
88
/// no-file
9-
<div class:big={big}>
9+
<button
10+
class="card"
11+
class:flipped={flipped}
12+
on:click={() => flipped = !flipped}
13+
>
1014
```
1115

1216
In those cases we can use a shorthand form:
1317

1418
```svelte
1519
/// file: App.svelte
16-
<div +++class:big+++>
17-
some {big ? 'big' : 'small'} text
18-
</div>
20+
<button
21+
class="card"
22+
+++class:flipped+++
23+
on:click={() => flipped = !flipped}
24+
>
1925
```

content/tutorial/03-advanced-svelte/06-classes/02-class-shorthand/app-a/src/lib/App.svelte

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)