$30 off During Our Annual Pro Sale. View Details »

Back to boring (part 2)

Back to boring (part 2)

stefan judis

July 11, 2023
Tweet

More Decks by stefan judis

Other Decks in Technology

Transcript

  1. @stefanjudis
    Back to boring

    View Slide

  2. @stefanjudis
    stefanjudis.com | webweekly.email
    Heyo,
    I'm Stefan!

    View Slide

  3. checklyhq.com

    View Slide

  4. webweekly.email

    View Slide

  5. This is all way too
    complicated and too much
    code for a website...
    My CTO from almost 10 years ago

    View Slide

  6. This is how
    we do it!

    View Slide

  7. SPA MPA
    SSG SSR Edge Rendering
    (Partial) Hydration
    Server Components
    Resumability

    View Slide

  8. SPA MPA
    SSG SSR Edge Rendering
    (Partial) Hydration
    Server Components
    Resumability
    It's a lot!

    View Slide

  9. View Slide

  10. View Slide

  11. Stefan, welcome to Canada!
    Access 1 MB of data for 1 Euro!
    (~1.46 CA$)

    View Slide

  12. 2013
    Hello world!
    10KB / 50KB
    2023
    Hello world!
    100KB / 300KB*
    Complexity
    * powered by 200MB+ of text files #node_modules

    View Slide

  13. cwvtech.report

    View Slide

  14. Core Web Vitals Technology Report

    View Slide

  15. View Slide

  16. Core Web Vitals Technology Report

    View Slide

  17. UX DX
    My misconception

    View Slide

  18. I do feel overwhelmed by the pace of change. [...]
    JavaScript is meant to feel overwhelming.
    It’s where we try stu! out.
    It’s where stu! moves fast.
    Jeremy Keith
    Source: "Building" presentation

    View Slide

  19. JavaScript
    CSS
    HTML
    HTTP

    View Slide

  20. The web platform
    wasn't ready...

    View Slide

  21. The web platform
    still isn't ready...

    View Slide

  22. The web platform
    still isn't ready...
    (but we'll get there sooner than later)

    View Slide

  23. A cross-browser effort to reach a state where
    each technology works exactly the same in every browser.
    Interop
    Source: wpt.fyi/interop-2023

    View Slide

  24. A cross-browser effort to reach a state where
    each technology works exactly the same in every browser.
    Interop
    Source: wpt.fyi/interop-2023

    View Slide

  25. Aspect Ratio Cascade Layers
    Color spaces and functions
    Dialog Grid Flex Subgrid
    Containment Scrolling
    Interop 2022
    *
    * This list is not complete.

    View Slide

  26. Container Queries
    :has() Inert @property
    Import Maps
    Font features color-mix
    :nth-child(of syntax)
    Interop 2023
    *
    * This list is not complete.

    View Slide

  27. open-ui.org

    View Slide

  28. View Slide

  29. How hard can it be
    to show a tooltip?

    View Slide

  30. Floating UI Popper

    View Slide

  31. View Slide

  32. View Slide

  33. .toggleBtn {
    anchor-name: -#my-anchor;
    }

    View Slide

  34. .toggleBtn {
    anchor-name: -#my-anchor;
    }
    #something {
    -#width: 15rem;
    -#height: 5rem;
    anchor-default: -#my-anchor;
    position-fallback: -#left-to-bottom;
    }

    View Slide

  35. .toggleBtn {
    anchor-name: -#my-anchor;
    }
    #something {
    -#width: 15rem;
    -#height: 5rem;
    anchor-default: -#my-anchor;
    position-fallback: -#left-to-bottom;
    }
    @position-fallback -#left-to-bottom {
    @try {
    top: calc(anchor(center) - var(-#height) / 2);
    left: calc(anchor(right));
    }
    @try {
    top: calc(anchor(center) - var(-#height) / 2);
    right: calc(anchor(left));
    left: auto;
    }
    }

    View Slide

  36. @position-fallback -#left-to-bottom {
    @try {
    top: calc(anchor(center) - var(-#height) / 2);
    left: calc(anchor(right));
    }
    @try {
    top: calc(anchor(center) - var(-#height) / 2);
    right: calc(anchor(left));
    left: auto;
    }
    }
    !

    View Slide

  37. Popover Anchor Positioning
    114 ✅
    17 #
    114 $
    117 #
    %
    &

    View Slide

  38. How hard can it be to
    write maintainable CSS?

    View Slide

  39. View Slide

  40. 1
    Variables
    2
    Color functions
    3
    Nesting

    View Slide

  41. Variables
    ?
    Color functions
    ?
    Nesting

    View Slide

  42. .box {
    background: PaleVioletRed;
    }
    #DB7093
    Relative colors

    View Slide

  43. .box {
    -#my-color: PaleVioletRed;
    background: var(-#my-color);
    }
    #DB7093
    Relative colors

    View Slide

  44. .box {
    -#my-color: PaleVioletRed;
    background: rgb(from var(-#my-color) r g b);
    }
    rgb(219 112 147)
    Relative colors

    View Slide

  45. .box {
    -#my-color: PaleVioletRed;
    background: rgb(from var(-#my-color) r g b);
    }
    rgb(219 112 147)
    Relative colors

    View Slide

  46. .box {
    -#my-color: PaleVioletRed;
    background: rgb(from var(-#my-color) g r b);
    }
    rgb(112 219 147)
    Relative colors

    View Slide

  47. .box {
    -#my-color: PaleVioletRed;
    background: rgb(from var(-#my-color) g b r);
    }
    rgb(112 147 219)
    Relative colors

    View Slide

  48. .box {
    -#my-color: PaleVioletRed;
    background: hsl(from var(-#my-color) h s l);
    }
    hsl(340deg 60% 65%)
    Relative colors

    View Slide

  49. .box {
    -#my-color: PaleVioletRed;
    background: hsl(from var(-#my-color) h s calc(l + 20%));
    }
    hsl(340deg 60% 85%)
    Relative colors

    View Slide

  50. .box {
    -#my-color: PaleVioletRed;
    background: hsl(from var(-#my-color) h 0% calc(l + 20%));
    }
    hsl(340deg 0% 85%)
    Relative colors

    View Slide

  51. .box {
    -#my-color: PaleVioletRed;
    background: oklch(from var(-#my-color) calc(l + 0.2) c h);
    }
    oklch(0.87 0.13 0.68)
    Relative colors

    View Slide

  52. colorInput.showPicker();
    hsl(from #38571a h s 0%)
    color-contrast(#38571a vs #000, #fff)
    (behind a flag)

    View Slide

  53. Variables Relative colors
    ?
    Nesting

    View Slide

  54. .card {
    .container {
    display: flex;
    flex-direction: column;
    gap: 1em;
    }
    .header {
    aspect-ratio: 3 / 2;
    }
    & h2, & p {
    margin: 0;
    }
    } Waiting for Firefox 116
    (Shipping in ~3 weeks)
    Photo by Ben Michel on Unsplash

    View Slide

  55. .card {
    .container {
    display: flex;
    flex-direction: column;
    gap: 1em;
    }
    .header {
    aspect-ratio: 3 / 2;
    }
    & h2, & p {
    margin: 0;
    }
    } Waiting for Firefox 116
    (Shipping in ~3 weeks)
    '
    Photo by Ben Michel on Unsplash

    View Slide

  56. Source: developer.chrome.com/articles/css-nesting/

    View Slide

  57. .card {
    h1 {}
    }
    .card {
    & h1 {}
    }
    .card {
    :is(h1) {}
    }
    Valid
    Valid
    X Invalid

    View Slide

  58. How hard can it be to create
    responsive UI components?

    View Slide

  59. .wide-nav {
    display: none;
    @media (min-width: 63rem) {
    display: flex;
    }
    }

    View Slide

  60. View Slide

  61. Source: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries

    View Slide

  62. .card {
    .container {
    display: flex;
    flex-direction: column;
    }
    }

    View Slide

  63. .card {
    container-type: inline-size;
    .container {
    display: flex;
    flex-direction: column;
    @container (width > 400px) {
    flex-direction: row;
    }
    }
    }

    View Slide

  64. .card {
    container-type: inline-size;
    .container {
    display: flex;
    flex-direction: column;
    @container (width > 400px) {
    flex-direction: row;
    .header {
    flex: 0 0 25cqw;
    }
    }
    }
    }

    View Slide

  65. .card {
    container-type: inline-size;
    .container {
    display: flex;
    flex-direction: column;
    @container (width > 400px) {
    flex-direction: row;
    .header {
    flex: 0 0 25cqw;
    }
    }
    }
    }
    cqw 1% of a query container's width
    cqh 1% of a query container's height
    cqi 1% of a query container's inline size
    cqb 1% of a query container's block size
    cqmin The smaller value of either cqi or cqb
    cqmax The larger value of either cqi or cqb

    View Slide

  66. .container {
    container-type: size;
    height: 12rem;
    }
    @container (orientation: portrait) {
    .portrait {
    display: grid;
    }
    .landscape {
    display: none;
    }
    }

    View Slide

  67. .card {
    container-type: inline-size;
    .container {
    display: flex;
    flex-direction: column;
    }
    }

    View Slide

  68. .card {
    container-type: inline-size;
    .container {
    display: flex;
    flex-direction: column;
    }
    &:has(img[src*="dog"]) {
    background: url(./dog.svg);
    }
    }
    Behind a flag

    View Slide

  69. article:has(aside) { /% ..' *) }
    form:has(:invalid) { /% ..' *) }
    :root:has(.menu-toggle[aria-pressed=”true”]) {
    /% ..' *)
    }
    label:has(+ input) { /% … *) }

    View Slide

  70. developer.chrome.com/blog/has-m105/

    View Slide

  71. CSS has become a more
    complete mature language,
    that works better with the
    way we build websites today.
    Una Kravets
    Source: The state of the CSS community

    View Slide

  72. How hard can it be to
    load a perfect image?

    View Slide


  73. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),

    View Slide

  74. sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>

    View Slide


  75. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>

    View Slide


  76. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>
    type="image/webp"

    View Slide


  77. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"

    View Slide


  78. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"

    View Slide


  79. srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=webp 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=webp 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px">
    srcset="
    https:/0images.ctfassets.net/..'/paris.jpg?w=100&fm=jpg&fl=progressive 100w,
    https:/0images.ctfassets.net/..'/paris.jpg?w=200&fm=jpg&fl=progressive 200w,
    ..'"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    src="https:/0images.ctfassets.net/..'/paris.jpg"
    alt="Buildings of Paris"
    loading="lazy"
    decoding="async"
    width="1243"
    height="1500">
    <1picture>
    loading="lazy"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"

    View Slide

  80. loading="lazy"
    width="200"
    height="200"
    sizes="
    (max-width: 768px) calc(100vw - 3em),
    (max-width: 1376px) calc(50vw - 8em),
    550px"
    srcset="swing-200.jpg 200w, swing-400.jpg 400w, ..'"
    src="swing-400.jpg"
    alt="Kettlebell Swing">

    View Slide

  81. loading="lazy"
    width="200"
    height="200"
    sizes="auto"
    srcset="swing-200.jpg 200w, swing-400.jpg 400w, ..'"
    src="swing-400.jpg"
    alt="Kettlebell Swing">

    View Slide

  82. loading="lazy"
    width="200"
    height="200"
    sizes="auto"
    srcset="swing-200.jpg 200w, swing-400.jpg 400w, ..'"
    src="swing-400.jpg"
    alt="Kettlebell Swing">
    If images are lazy loaded,
    let the browser pick the best size.

    View Slide

  83. loading="lazy"
    width="200"
    height="200"
    sizes="auto"
    srcset="swing-[width].jpg [width]w"
    src="swing-400.jpg"
    alt="Kettlebell Swing">

    View Slide

  84. loading="lazy"
    width="200"
    height="200"
    sizes="auto"
    srcset="swing-[width].jpg [width]w"
    src="swing-400.jpg"
    alt="Kettlebell Swing">
    Could this be a thing?

    View Slide

  85. How hard can it be to
    build delightful UI?

    View Slide

  86. View Slide

  87. codepen.io/stefanjudis/pen/abQLvOW

    View Slide

  88. function transitionStuff(data) {
    /0 For non-Chromiums
    if (!document.startViewTransition) {
    updateTheDOMSomehow();
    return;
    }
    /0 browser: ( (old)
    document.startViewTransition(() =3 {
    updateTheDOMSomehow();
    /0 browser: ( (new)
    })
    }

    View Slide

  89. View Slide

  90. View Slide

  91. View Slide

  92. movies.nuxt.space
    export default defineNuxtConfig({
    experimental: {
    viewTransition: true
    }
    })

    View Slide

  93. live-transitions.pages.dev

    View Slide

  94. Multipage transitions

    View Slide

  95. stefanjudis.com

    View Slide

  96. smashing-transitions.netlify.app

    View Slide

  97. developer.chrome.com/docs/web-platform/view-transitions/

    View Slide

  98. The web platform
    is catching up!

    View Slide

  99. JavaScript leads the
    way to the "next web"...

    View Slide

  100. ... coming with a better user
    and developer experience!

    View Slide

  101. Video platforms Blogs Shops
    Image & Illustration software
    Marketing sites Games
    Productivity Apps PWAs
    Streaming sites Social Networks

    View Slide

  102. If your site feels like
    a "boring" Multi Page App,
    maybe it should be one?

    View Slide

  103. If JavaScript doesn't bring users joy,
    thank it, and throw it away.
    Marie Kondo

    View Slide

  104. If JavaScript doesn't bring users joy,
    thank it, and throw it away.
    Marie Kondo Addy Osmani
    Source: The Cost of JavaScript 2023

    View Slide

  105. @stefanjudis
    stefanjudis.com | webweekly.email
    Thanks.

    View Slide