From 6d872f8393fd0703208d80e58b9652b746852237 Mon Sep 17 00:00:00 2001 From: David Khourshid Date: Wed, 11 May 2022 07:42:11 -0400 Subject: [PATCH] Initial commit --- 00-fundamentals/index.html | 41 +++- 00-fundamentals/readme.md | 30 +++ 00-fundamentals/style.scss | 124 ++++++++++ 01-transitions/index.html | 7 +- 01-transitions/readme.md | 16 ++ 01-transitions/style.scss | 58 +++++ 02-keyframes/readme.md | 14 ++ 03-choreography/readme.md | 14 ++ 04-states/readme.md | 19 ++ 04-states/style.scss | 1 + 05-layout/index.html | 41 +++- 05-layout/readme.md | 22 ++ 05-layout/style.scss | 51 +++++ 06-reactive/index.html | 29 ++- 06-reactive/readme.md | 4 + 06-reactive/style.scss | 12 + examples/inflight/index.html | 187 +++++++++++++++ examples/inflight/style.scss | 431 +++++++++++++++++++++++++++++++++++ index.html | 15 +- styles/base.scss | 36 ++- vite.config.js | 1 + 21 files changed, 1142 insertions(+), 11 deletions(-) create mode 100644 00-fundamentals/readme.md create mode 100644 01-transitions/readme.md create mode 100644 02-keyframes/readme.md create mode 100644 03-choreography/readme.md create mode 100644 04-states/readme.md create mode 100644 05-layout/readme.md create mode 100644 06-reactive/readme.md create mode 100644 examples/inflight/index.html create mode 100644 examples/inflight/style.scss diff --git a/00-fundamentals/index.html b/00-fundamentals/index.html index 91e898e..9ad366d 100644 --- a/00-fundamentals/index.html +++ b/00-fundamentals/index.html @@ -7,5 +7,44 @@ Fundamentals - + +
+ + +
+ + diff --git a/00-fundamentals/readme.md b/00-fundamentals/readme.md new file mode 100644 index 0000000..c30f035 --- /dev/null +++ b/00-fundamentals/readme.md @@ -0,0 +1,30 @@ +# Lesson 0: Fundamentals + +- Why animate? Guidance and clarification, style and branding. +- Duration: how long an _iteration_ of an animation takes to complete. +- Delay: how long it takes before an animation _starts_ +- Timing function: the _easing_ of an animation +- CSS Variables: custom properties that can be inherited by elements and set by JavaScript: + +```css +:root { + --duration: 2s; +} + +.thing { + animation-duration: calc(var(--duration, 1s)); +} +``` + +```js +const thingEl = document.querySelector('.thing'); + +thingEl.style.setProperty('--color', 'green'); +``` + +## Resources + +- [Ground Rules for CSS Animations](https://css-tricks.com/ground-rules-for-web-animations/) +- [UX Animation Principles: Duration](https://codepen.io/team/keyframers/pen/gdJJZV) +- [UX Animation Principles: Stagger](https://codepen.io/team/keyframers/pen/GXaaNw) +- [UX Animation Principles: Acceleration](https://codepen.io/team/keyframers/pen/ZqbWao) diff --git a/00-fundamentals/style.scss b/00-fundamentals/style.scss index dbca56e..95a371b 100644 --- a/00-fundamentals/style.scss +++ b/00-fundamentals/style.scss @@ -1 +1,125 @@ @import '../styles/base.scss'; + +:root { + --color-gray: #8c97b7; + --color-blue: #1c38f1; + --color-green: #1fcdb0; + --input-height: 3rem; + --transition-duration: 0.3s; + --transition-easing: cubic-bezier(0.5, 0, 0.5, 1); + --animation-duration: 0.8s; +} +body { + display: flex; + justify-content: center; + align-items: center; + background-color: #f9fbff; +} + +.ui-form { + background: #fff; + box-shadow: 0 0.5rem 1rem #0003; + padding: 1rem; + border-radius: 0.25rem; + display: grid; + grid-template-columns: 1fr auto; + grid-template-rows: 1fr; + grid-column-gap: 1rem; + grid-template-areas: 'input button'; + transition: all var(--transition-duration) var(--transition-easing); + will-change: transform; + + --color: var(--color-gray); + &:focus-within { + --color: var(--color-blue); + } + + &[data-state='subscribe'] { + animation: slide-up var(--animation-duration) var(--transition-easing); + } + + &[data-state='success'] { + --color: var(--color-green); + } + + &[data-state='error'] { + --color: var(--color-red, red); + animation: shake 1s ease; + } + + > .ui-input, + > .ui-button { + animation-name: slide-up; + animation-fill-mode: both; + animation-timing-function: var(--transition-easing); + animation-delay: calc(var(--animation-duration) / 2); + } + + > .ui-input { + animation-duration: 0.5s; + } + > .ui-button { + animation-duration: 0.6s; + } +} + +.ui-input { + grid-area: input; + padding: 0 1rem; + height: var(--input-height); + border: 2px solid var(--color); + border-radius: 0.25rem; + outline: none; + transition: inherit; +} + +.ui-button { + grid-area: button; + border: none; + padding: 0 1rem; + color: white; + font-weight: bold; + border-radius: 0.25rem; + height: var(--input-height); + background-color: var(--color); + transition: inherit; +} + +[data-show]:not([data-active]) { + display: none; +} + +.ui-form { + overflow: hidden; +} + +@keyframes slide-up { + from { + opacity: 0; + transform: translateY(100%); + } + to { + opacity: 1; + transform: none; + } +} + +@keyframes shake { + 20%, + 40%, + 60%, + 80% { + transform: translateX(1%); + } + 10%, + 30%, + 50%, + 70%, + 90% { + transform: translateX(-1%); + } + from, + to { + transform: none; + } +} diff --git a/01-transitions/index.html b/01-transitions/index.html index c0ff8f3..1c03646 100644 --- a/01-transitions/index.html +++ b/01-transitions/index.html @@ -7,5 +7,10 @@ Transitions - + +
+ + +
+ diff --git a/01-transitions/readme.md b/01-transitions/readme.md new file mode 100644 index 0000000..f4dc644 --- /dev/null +++ b/01-transitions/readme.md @@ -0,0 +1,16 @@ +# Lesson 1: Transitions + +- [`transition-property`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-property) +- [`transition-duration`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-duration) +- [`transition-delay`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-delay) +- [`transition-timing-function`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function) +- [`transition`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition) (shorthand) + +## Exercise + +- Add border-color transitions for the different states of the input field. +- Add background-color transitions for the different states of the button. + +## Resources + +- [Springy Switchbox](https://codepen.io/team/keyframers/pen/JVdxzz) diff --git a/01-transitions/style.scss b/01-transitions/style.scss index dbca56e..1031aba 100644 --- a/01-transitions/style.scss +++ b/01-transitions/style.scss @@ -1 +1,59 @@ @import '../styles/base.scss'; + +body { + display: flex; + justify-content: center; + align-items: center; + background-color: #ECF5F7; +} + +.ui-form { + display: flex; + flex-direction: column; + gap: 1rem; + background-color: #fff; + padding: 2rem; + box-shadow: 0 .5rem 1rem #0001; + border-radius: .25rem; +} + +.ui-input { + appearance: none; + background-color: #F7FAFC; + border: 2px solid #eee; + border-radius: .25rem; + transition: 0.3s all ease-in-out; + padding: 1rem; + outline: none; + + &:hover, &:focus { + border-color: #bbb; + } + + &:focus { + border-color: #2146B3; + background-color: #fff; + } +} + +.ui-button { + background-color: #2146B3; + color: white; + padding: 1rem; + display: block; + appearance: none; + border: none; + outline: 2px solid transparent; + outline-offset: 2px; + transition: all .3s; + border-radius: .25rem; + cursor: pointer; + + &:focus { + outline: 2px solid #2146b3; + } + + &:active { + opacity: 0.8; + } +} diff --git a/02-keyframes/readme.md b/02-keyframes/readme.md new file mode 100644 index 0000000..07e7706 --- /dev/null +++ b/02-keyframes/readme.md @@ -0,0 +1,14 @@ +# Lesson 2: Keyframes and animations + +- [`@keyframes`](https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes) +- [`animation-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-name) (shorthand) +- [`animation-duration`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-duration) +- [`animation-delay-delay`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-delay-delay) +- [`animation-timing-function`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function) +- [`animation-fill-mode`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode) +- [`animation`](https://developer.mozilla.org/en-US/docs/Web/CSS/animation) (shorthand) + +## Exercise + +- Add an entry animation to the form. +- Create a shake animation; we will use this later. diff --git a/03-choreography/readme.md b/03-choreography/readme.md new file mode 100644 index 0000000..0b43a71 --- /dev/null +++ b/03-choreography/readme.md @@ -0,0 +1,14 @@ +# Lesson 3: Choreography + +- Staggered animations +- Planning choreographed animations + +## Exercise + +- Stagger the entrance of the input and button. +- Then, choreograph the entrance so that the button appears after the input. + +## Resources + +- [UX Animation Principles: Choreography](https://codepen.io/team/keyframers/pen/yRYJPr) +- [UX Animation Principles: Grid](https://codepen.io/team/keyframers/pen/bmVejm) diff --git a/04-states/readme.md b/04-states/readme.md new file mode 100644 index 0000000..10b7ff7 --- /dev/null +++ b/04-states/readme.md @@ -0,0 +1,19 @@ +# Lesson 4: States + +- Determining states for animation +- [Data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) +- Creating simple state machines + +## Exercise + +- Use JavaScript to change the state of the form from `'subscribe'` to `'loading'` when the button is clicked. +- After 2 seconds in `'loading'`, change the state to `'success'` or `'error'` (chosen randomly to simulate an error state) + - Hint: use `Math.random() < 0.5` +- On the `'error'` state, animate the form by shaking it + - You will need to create a `shake` animation with `@keyframes` +- Refactor to a state machine to send events and prevent impossible state transitions (we'll do this together) + +## Resources + +- [Expanding Video Player](https://codepen.io/team/keyframers/pen/dLjZEO) +- [Contact Form Transitions](https://codepen.io/team/keyframers/pen/YzwGZwN) diff --git a/04-states/style.scss b/04-states/style.scss index 6a8c268..71243ac 100644 --- a/04-states/style.scss +++ b/04-states/style.scss @@ -1,3 +1,4 @@ +@import '../styles/base.scss'; body { background: #000; diff --git a/05-layout/index.html b/05-layout/index.html index b3ca8ac..452d4fa 100644 --- a/05-layout/index.html +++ b/05-layout/index.html @@ -7,5 +7,44 @@ Layout - + +
+
+
+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Inventore + ullam hic consectetur ducimus neque ipsam incidunt voluptatem + voluptatum eos. Voluptatum minus omnis provident sit architecto, + mollitia nihil aspernatur sed praesentium. +

+
+
+ + diff --git a/05-layout/readme.md b/05-layout/readme.md new file mode 100644 index 0000000..6f05de8 --- /dev/null +++ b/05-layout/readme.md @@ -0,0 +1,22 @@ +# Lesson 5: Layout animations + +- FLIP technique + 1. First + 2. Last + 3. Invert + 4. Play + +## Exercise + +- Use JavaScript to change the state of the form from `'subscribe'` to `'loading'` when the button is clicked. +- After 2 seconds in `'loading'`, change the state to `'success'` or `'error'` (chosen randomly to simulate an error state) + - Hint: use `Math.random() < 0.5` +- On the `'error'` state, animate the form by shaking it + - You will need to create a `shake` animation with `@keyframes` +- Refactor to a state machine to send events and prevent impossible state transitions (we'll do this together) + +## Resources + +- https://codepen.io/davidkpiano/pen/EbwrQQ +- [FLIP Transition with CSS Variables](https://codepen.io/team/keyframers/pen/MWaoyNQ) +- [FLIP Between States](https://codepen.io/team/keyframers/pen/xxVOLeM) diff --git a/05-layout/style.scss b/05-layout/style.scss index dbca56e..516d64f 100644 --- a/05-layout/style.scss +++ b/05-layout/style.scss @@ -1 +1,52 @@ @import '../styles/base.scss'; + +body { + display: flex; + justify-content: center; + align-items: center; +} + +#app { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; + grid-template-areas: 'figure'; + grid-column-gap: 2rem; + width: 10vw; + aspect-ratio: 1; + border: 1px solid; + + &[data-state='collapsed'] { + .ui-content { + display: none; + } + } + + &[data-state='expanded'] { + padding: 2rem; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr; + grid-template-areas: 'figure content'; + aspect-ratio: 2; + width: 50vw; + } +} + +.ui-content { + grid-area: content; +} + +.ui-figure { + background: blue; + transform-origin: top left; + + &[data-flip='invert'] { + transform: translate(calc(var(--dx) * 1px), calc(var(--dy) * 1px)) + scale(var(--dw), var(--dh)); + } + + &[data-flip='play'] { + transition: transform 0.3s; + transform: none; + } +} diff --git a/06-reactive/index.html b/06-reactive/index.html index 3f2c872..b1a6487 100644 --- a/06-reactive/index.html +++ b/06-reactive/index.html @@ -7,5 +7,32 @@ Reactive - + +
+ + diff --git a/06-reactive/readme.md b/06-reactive/readme.md new file mode 100644 index 0000000..61d0eec --- /dev/null +++ b/06-reactive/readme.md @@ -0,0 +1,4 @@ +## Resources + +- [Circular Mask Transition with CSS](https://codepen.io/team/keyframers/pen/jRaLgX) +- [Diamond Slider](https://codepen.io/team/keyframers/pen/ExWGGpX) diff --git a/06-reactive/style.scss b/06-reactive/style.scss index dbca56e..f6c34dc 100644 --- a/06-reactive/style.scss +++ b/06-reactive/style.scss @@ -1 +1,13 @@ @import '../styles/base.scss'; + +.circle { + height: 5vmin; + width: 5vmin; + border-radius: 50%; + background-color: blue; + + transform: translate( + calc((var(--x) * 1px) - 50%), + calc((var(--y) * 1px) - 50%) + ); +} diff --git a/examples/inflight/index.html b/examples/inflight/index.html new file mode 100644 index 0000000..3f50223 --- /dev/null +++ b/examples/inflight/index.html @@ -0,0 +1,187 @@ + + + + + + + Document + + + +
+ +
+
+
🕖
+
2hr 56m Until Arrival
+
Flight Tracker
+
+
⚙️
+
+
+
+
+
Movies
+
+
Artist Spotlight
+
Details
+
+
+
+ +
+
+
+
New Releases
+
+
+
    +
  • +
    +
    Some movie
    +
  • +
  • +
    +
    Some movie
    +
  • +
  • +
    +
    Some movie
    +
  • +
  • +
    +
    Some movie
    +
  • +
  • +
    +
    Some movie
    +
  • +
+
+ +
+
+
+
Playlists
+
+
+
    +
  • +
    +
    +
    Deep Focus Playlist
    + Various Artists +
    +
  • +
  • +
    +
    +
    Jazz Playlist
    + Various Artists +
    +
  • +
  • +
    +
    +
    Classical Playlist
    + Various Artists +
    +
  • +
  • +
    +
    +
    Rock Playlist
    + Various Artists +
    +
  • +
  • +
    +
    +
    Electronica Playlist
    + Various Artists +
    +
  • +
+
+
+
+
+
+

Delta One

+

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Nesciunt, + consequuntur laboriosam excepturi tempore cumque dolorum minus esse + praesentium numquam nobis deserunt molestiae velit obcaecati + quibusdam porro eos placeat possimus incidunt. +

+ +
+
+
+ +
Welcome to Frontend Airlines
+
Get Started
+
+
+ + + diff --git a/examples/inflight/style.scss b/examples/inflight/style.scss new file mode 100644 index 0000000..b7a46a0 --- /dev/null +++ b/examples/inflight/style.scss @@ -0,0 +1,431 @@ +@import '../styles/base.scss'; + +:root { + --color-bg-light: #19305b; + --color-bg-dark: #152547; + --color-secondary: #d62d1f; + --color-secondary-light: #dc594e; +} + +body { + display: flex; + justify-content: center; + align-items: center; + background-color: #111; +} + +#app { + display: grid; + grid-template-columns: 15rem 1fr; + grid-template-rows: auto 1fr; + grid-row-gap: 1rem; + grid-template-areas: + 'aside header' + 'aside main'; + background-color: var(--color-bg-light); + height: 50vw; + width: 90vw; + color: white; + overflow: hidden; +} + +aside { + grid-area: aside; + background: var(--color-bg-dark); +} + +.ui-nav { + display: grid; + grid-template-rows: 4rem 4fr 1fr; + grid-template-columns: 1fr; + grid-template-areas: + 'logo' + 'items' + 'search'; + + > .ui-nav-items { + grid-area: items; + } +} + +.ui-flight-header { + grid-area: header; + display: grid; + grid-template-columns: 1fr auto; + grid-template-areas: 'flight-info settings'; + align-items: center; + padding: 0 2rem; + height: 4rem; + font-size: 85%; +} + +main { + grid-area: main; + overflow: hidden; + + > section { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + } +} + +.ui-screen { + z-index: 1; + + &:not([data-active]) { + opacity: 0; + z-index: 0; + } +} + +.ui-screen:not([data-active]) { + opacity: 0; + z-index: 0; +} + +[data-screen='home'] { + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-end; + .ui-interest { + padding: 1rem 2rem; + background-color: #0003; + } + .ui-interest-details { + display: flex; + flex-direction: row; + gap: 1rem; + } + + .ui-interest-title { + font-size: 2rem; + } +} + +[data-screen='movies'] { + display: grid; + grid-template-rows: 3rem 1fr; + grid-template-columns: 1fr; + grid-template-areas: 'header' 'movies'; + grid-row-gap: 1rem; + opacity: 1; + transition: opacity 0.3s; + + &:not([data-active]) { + opacity: 0; + } + + > .ui-screen-header { + grid-area: header; + } +} + +.ui-screen-header { + z-index: 1; + padding: 0 2rem; + display: grid; + grid-template-columns: 1fr; + align-items: stretch; + grid-column-gap: 1rem; +} + +// Movies +// ------ + +.ui-movies { + display: flex; + flex-direction: row; + gap: 1rem; + overflow-x: auto; +} + +.ui-movie { + display: grid; + grid-template-rows: 1fr 3rem; + grid-template-areas: + 'cover' + 'title'; + grid-row-gap: 1rem; + aspect-ratio: 0.6; + height: 100%; + flex-shrink: 0; + + &:first-child { + margin-left: 2rem; + } + &:last-child { + margin-right: 2rem; + } +} + +.ui-movie-cover { + background: linear-gradient(to bottom right, #0d98bb, #1accfa); +} + +.ui-nav-items { + margin: 0; + padding: 0; + list-style: none; +} + +.ui-nav-item { + color: white; + font-weight: bold; + padding-inline: 2rem 3rem; + height: 3rem; + display: flex; + align-items: center; + // padding: 1rem 2rem 1rem 3rem; + + &:hover, + &[data-active] { + background: #061226; + } +} + +.ui-flight-info { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + grid-area: flight-info; + opacity: 0.6; + gap: 1rem; +} + +.ui-dropdown { + background: var(--color-bg-dark); + display: flex; + flex-direction: row; + align-items: center; + padding: 0 1rem; +} + +.ui-dropdown-title { + font-size: 1.2rem; +} + +.ui-dropdown-content { + position: absolute; + top: 100%; + width: 100%; + height: 50vh; + background-color: #fff; + z-index: 100; +} + +.ui-overlay { + position: absolute; + z-index: 10; + top: 0; + left: 0; + width: 100%; + height: 100%; + transition: all 0.3s; + display: block; + + .ui-figure { + background-color: #fff; + } + + &:not([data-active]) { + transform: translateY(100%); + } +} + +[data-screen='about'] { + display: grid; + grid-template-columns: 3fr 2fr; + grid-template-rows: 1fr; + grid-column-gap: 2rem; + grid-template-areas: 'figure description'; + background: var(--color-bg-dark); +} + +.ui-button { + background-color: var(--color-secondary); + color: white; + padding: 0.75rem 2rem; + border: none; + border-radius: 0.25rem; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font-weight: 600; + cursor: pointer; + transition: all 0.3s; + + &:hover { + background-color: var(--color-secondary-light); + } +} + +.ui-close { + position: absolute; + appearance: none; + top: 0; + right: 0; + background: transparent; + border: none; + color: inherit; + padding: 1rem; +} + +[data-show]:not([data-active]) { + display: none; +} + +@keyframes slide-up { + from { + transform: translateY(100%); + } + to { + transform: none; + } +} + +@keyframes slide-down { + from { + transform: none; + } + to { + transform: translateY(100%); + } +} + +// Music screen +// ---------------------------- + +[data-screen='music'] { + display: grid; + grid-template-rows: 3rem 1fr; + grid-template-columns: 1fr; + grid-template-areas: 'header' 'music'; + grid-row-gap: 1rem; + opacity: 1; + transition: opacity 0.3s; + + &:not([data-active]) { + opacity: 0; + } + + > .ui-screen-header { + grid-area: header; + } +} + +.ui-albums { + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 1rem; + overflow-x: auto; +} + +.ui-albums-header { + z-index: 1; + padding: 0 2rem; + display: grid; + grid-template-columns: 1fr; + align-items: stretch; + grid-column-gap: 1rem; +} + +.ui-album { + display: grid; + grid-template-rows: 1fr auto; + grid-template-areas: + 'cover' + 'title'; + width: 20vw; + flex-shrink: 0; + background-color: var(--color-bg-dark); + + &:first-child { + margin-left: 2rem; + } + &:last-child { + margin-right: 2rem; + } +} + +.ui-album-title { + padding: 2rem; + + > small { + display: block; + opacity: 0.8; + } +} + +.ui-album-cover { + background: linear-gradient(to bottom right, #0d98bb, #1accfa); + aspect-ratio: 1; +} + +// Welcome screen +// ----------------------------------------------------- + +[data-screen='welcome'] { + background: var(--color-bg-dark); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 1rem; + + .ui-logo { + font-size: 3rem; + animation: welcome-logo 2s ease-in-out both; + } + .ui-title { + animation: welcome-title 2s ease-in-out both; + } + .ui-button { + animation: welcome-button 2s ease-in-out both; + } +} + +// 0s: logo scale 0 +// 1s: logo scale 1 +// 2s: text + button appear + +@keyframes welcome-logo { + from { + transform: translateY(100%) scale(0); + } + 50% { + transform: translateY(100%) scale(1); + } + to { + transform: none; + } +} + +@keyframes welcome-title { + from, + 50% { + opacity: 0; + transform: translateY(100%); + } + to { + opacity: 1; + transform: none; + } +} +@keyframes welcome-button { + from, + 55% { + opacity: 0; + transform: translateY(100%); + } + to { + opacity: 1; + transform: none; + } +} diff --git a/index.html b/index.html index f1dedb5..10bcd77 100644 --- a/index.html +++ b/index.html @@ -4,10 +4,19 @@ - Vite App + Frontend Masters CSS Animations Workshop -
- +
+

CSS Animation Workshop

+ Fundamentals + Transitions + Keyframe Animations + Choreography + States + Layout Animations + Reactive Animations + Inflight Example +
diff --git a/styles/base.scss b/styles/base.scss index b31ef69..d81d6ca 100644 --- a/styles/base.scss +++ b/styles/base.scss @@ -1,16 +1,44 @@ -html, body { +html, +body { height: 100%; width: 100%; margin: 0; padding: 0; + font-family: sans-serif; + font-size: 18px; + line-height: 1.6; } -*,*:before, *:after { +*, +*:before, +*:after { box-sizing: border-box; position: relative; } +input, +button { + font-size: inherit; +} -body { - background: green; +ul { + list-style: none; + padding: 0; + margin: 0; +} + +figure { + margin: 0; +} + +button { + appearance: none; +} + +// reduce or no-preference +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0s !important; + transition-duration: 0s !important; + } } diff --git a/vite.config.js b/vite.config.js index aca47cc..dfc9297 100644 --- a/vite.config.js +++ b/vite.config.js @@ -13,6 +13,7 @@ module.exports = defineConfig({ states: resolve(__dirname, '04-states/index.html'), layout: resolve(__dirname, '05-layout/index.html'), reactive: resolve(__dirname, '06-reactive/index.html'), + examples: resolve(__dirname, 'examples'), }, }, },