• Reusable components
  • Optimize responsive layout
  • Media queries \ config options \ other
1 / 58
1
  • Reusable components
  • Optimize responsive layout
  • Media queries \ config options \ other
2

3
4

Share

5

6

Goals

As a user:

  • I want to less or more information depending on the size of the widget.
  • On the dashboard page, I want to choose the size of the widget.

As a developer:

  • I want to reuse the same component throughout different layouts.
7

Goals

As a user:

  • I want to less or more information depending on the size of the widget.
  • On the dashboard page, I want to choose the size of the widget.

As a developer:

  • I want to reuse the same component throughout different layouts.
8

Media queries?

.widget { inline-size: 100%; }

@media (inline-size >= 480px) {
  .widget { inline-size: 100%; }
}

@media (inline-size >= 768px) {
  .widget { inline-size: 50%; }
}

@media (inline-size >= 1024px) {
  .widget { inline-size: 33.33%; }
}
9

Media queries?

.widget { inline-size: 100%; }

@media (inline-size >= 480px) {
  .widget { inline-size: 50%; }
}

@media (inline-size >= 768px) {
  .widget { inline-size: 33.33%; }
}
10

Media queries?

.widget { inline-size: 100%; }

@media (inline-size >= 480px) {
  .widget.page-article { inline-size: 50%; }
}

@media (inline-size >= 768px) {
  .widget { inline-size: 50%; }
  .widget.page-article { inline-size: 33.33%; }
}

@media (inline-size >= 1024px) {
  .widget { inline-size: 33.33%; }
}
11

Media queries?

.widget { inline-size: 100%; }

@media (inline-size >= 480px) {
  .widget.page-article { inline-size: 50%; }
  .widget.page-contact-form { inline-size: 89%; }
}

@media (inline-size >= 768px) {
  .widget { inline-size: 50%; }
  .widget.page-article { inline-size: 33.33%; }
  .widget.page-contact-form { inline-size: 12.78%; }
}

@media (inline-size >= 1024px) {
  .widget { inline-size: 33.33%; }
  .widget.page-contact-form { inline-size: 52%; }
}
12

Media queries?

.widget { inline-size: 100%; }

@media (inline-size >= 480px) { /* ... */ }

@media (inline-size >= 661px) {
  .page-whateva { inline-size: 651%; }
}

@media (inline-size >= 768px) { /* ... */ }

@media (inline-size >= 678px) {
  .page-whateva { inline-size: 56%; }
}
13

Media queries?

  • Query the viewport
  • Insufficient flexibility
14

Config options?

<internal-dashboard>
  <bar-widget />
  <pie-widget />
  <weather-widget size="large" />
  <users-widget />
</internal-dashboard>
internal-dashboard {}

weather-widget {}
weather-widget[size="large"] {}
weather-widget[size="small"] {}
15

Config options?

weather-widget {}

@media (inline-size >= 480px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
}

@media (inline-size >= 768px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
}

@media (inline-size >= 1024px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
}
16
weather-widget {}

@media (inline-size >= 480px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
  .page-whateva weather-widget[size="large"] {}
  .page-whateva weather-widget[size="small"] {}
}

@media (inline-size >= 768px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
  .page-whateva weather-widget[size="large"] {}
  .page-whateva weather-widget[size="small"] {}
}

@media (inline-size >= 1024px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
  .page-whateva weather-widget[size="large"] {}
  .page-whateva weather-widget[size="small"] {}
}
17

Config options?

  • End user is responsible for styling
  • End-user has to implement own layout logic
  • Not automatically provided
18

ResizeObserver?

const $widget = document.querySelector(".widget");

const resizeObserver = new ResizeObserver((entries) => {
  for (let entry of entries) {
    if (entry.target.width > 640) {
      entry.target.classList.add("widget--large");
    } else {
      entry.target.classList.remove("widget--large");
    }
  }
});

resizeObserver.observe($widget);
Layout shift
19

Layout shift - 1 - Empty
20

Layout shift - 2 - CSS ready
21

Layout shift - 3 - JS ready
22

CSS

23

24

25

Container
Queries

26
  • Size
  • Units
  • Style
27
  • Size
  • Units
  • Style
28

Size container queries

Which container can be queried for it’s size?


.product {
  container-type: size;
}

container-type values
sizex- and y-axis
inline-sizex-axis
normalDisable element as query container for container size queries
29

Size container queries

For what condition should we query?


@container (inline-size >= 400px) {}


container-type: size
  • width
  • height
  • inline-size
  • block-size
  • aspect-ratio
  • orientation (landscape, portrait)
container-type: inline-size
  • width
  • inline-size
30

Size container queries

Single condition

.product {
  container-type: inline-size;
}

.product-body {
  @container (inline-size >= 400px) { 
    /* ... */ 
  }
}

31

Size container queries

Multiple conditions

.product {
  container-type: size;
}

.product-body {
  @container (inline-size >= 400px) and (block-size >= 200px) {
    /* ... */  
  }
}
32

Size container queries

Target multiple containers

.page {
  container-type: size;
  container-name: folio;
}

.product-list {
  container-type: inline-size;
  container-name: list;
}

.product {
  @container folio (inline-size >= 400px) and (block-size >= 200px) { /* ... */  }
  @container list (inline-size >= 800px) { /* ... */ }
}
33

Size container queries

container shorthand

.page {
  container: folio / size;
}

.product-list {
  container: list / inline-size;
}

.product {
  @container folio (inline-size >= 400px) and (block-size >= 200px) { /* ... */  }
  @container list (inline-size >= 800px) { /* ... */ }
}
34

Size container queries

Containment always has to be set on an ancestor.

.ancestor {
  container-type: inline-size;
}

@container (inline-size >= 800px) {
  .ancestor {
    /* NOPE */
  }
}
35

Size container queries

Containment always has to be set on an ancestor, because of the normal flow.

Credits: Normal Flow by Miriam Suzanne

36
37
38
39
40
  • Size
  • Units
  • Style
41

Container relative units

.product {
  container-type: size;
}

.product-grandchild {
  block-size: 100cqb;
}
unitrelative to
cqw1% of a query container’s width
cqh1% of aquery container’s height
cqi1% of a query container’s inline size
cqb1% of a query container’s block size
cqminThe smaller value of cqi or cqb
cqmaxThe larger value of cqi or cqb
42
43
44
  • Size
  • Units
  • Style
45

Style container queries

Query computed styles of query container.

.product {
  container-type: normal;
}

.product-body {
  @container style(background: red) {
    /* ... */
  }
}
46

Style container queries

= CSS conditionals

47
48
49

W.I.I.F.U. ?

What's in it for us?
50
.dashboard {}
.page-whateva .dashboard {}
weather-widget {}
/* ... */

@media (inline-size >= 480px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
  .page-whateva weather-widget[size="large"] {}
  .page-whateva weather-widget[size="small"] {}  
}

@media (inline-size >= 768px) {
  weather-widget[size="large"] {}
  weather-widget[size="small"] {}
  .page-whateva weather-widget[size="large"] {}
  .page-whateva weather-widget[size="small"] {}
}
@media (inline-size >= 1024px) { 
  /* ... */
}

/* ... */
51
/* weather-widget.css */

.widget {
  container-type: inline-size;
}

.widget-body {
  @container (inline-size >= 480px) {}
  @container (inline-size >= 768px) {}
  @container (inline-size >= 1024px) {}
}
52
/* weather-widget.css */

.widget {
  container-type: inline-size;

  --wdgt-feature-a: false;
}

.widget-body {
  @container (inline-size >= 480px) {
    --wdgt-feature-a: true;
  }
}

.widget-temperature {
  display: none;

  @container style(--wdgt-feature-a: true) {
    display: block;
  }
}
53
54

Container
Queries

55

#TIL

Container queries

  • Encapsulate adaptive styles
  • Modular front-end architecture

Support in all major browser engines:

  • Size queries
  • Container Relative units

Partial support in Chrome

  • Style queries

56

Share

mrtnvh.com
57
58