Skip to content

CSS β€” Π‘ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ Layout ​

πŸ’» subgrid ​

Π’Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ элСмСнт участвуСт Π² Ρ€ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΡΠΊΠΎΠΉ сСткС β€” ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π²Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°ΡŽΡ‚ΡΡ автоматичСски:

css
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

/* ΠšΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠ° Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ всС 3 ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ своСй строки */
.card {
  display: grid;
  grid-column: span 3;
  grid-template-columns: subgrid;  /* наслСдуСт ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ родитСля */
}

/* Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠΈΠΌΠΎΠ΅ ΠΊΠ°Ρ€Ρ‚ΠΎΡ‡ΠΊΠΈ выравниваСтся ΠΏΠΎ ΠΎΠ±Ρ‰Π΅ΠΉ сСткС */
.card__image   { grid-column: 1; }
.card__content { grid-column: 2; }
.card__actions { grid-column: 3; }
css
/* Subgrid ΠΏΠΎ строкам */
.card {
  grid-row: span 3;
  grid-template-rows: subgrid;
  /* header, content, footer всСх ΠΊΠ°Ρ€Ρ‚ΠΎΡ‡Π΅ΠΊ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅ */
}

πŸ’» ЛогичСскиС свойства ​

ВмСсто top/right/bottom/left β€” block/inline. АвтоматичСски Π°Π΄Π°ΠΏΡ‚ΠΈΡ€ΡƒΡŽΡ‚ΡΡ ΠΊ RTL ΠΈ Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ°ΠΌ:

css
/* ВмСсто margin-left / margin-right */
.text {
  margin-inline: auto;          /* Ρ†Π΅Π½Ρ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ */
  margin-inline-start: 1rem;    /* left Π² LTR, right Π² RTL */
  margin-inline-end: 1rem;
}

/* ВмСсто margin-top / margin-bottom */
.section {
  margin-block: 2rem;
  padding-block: 1rem;
}

/* ВмСсто top/right/bottom/left Π² position */
.tooltip {
  inset: 0;                  /* top:0; right:0; bottom:0; left:0; */
  inset-block-start: 1rem;   /* top Π² Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅ */
  inset-inline-end: 1rem;    /* right Π² LTR */
}

/* ВмСсто width/height */
.box {
  inline-size: 200px;    /* width */
  block-size: 100px;     /* height */
  max-inline-size: 100%; /* max-width */
}

/* border, border-radius */
.card {
  border-block-end: 1px solid #e5e7eb;   /* border-bottom */
  border-inline-start: 4px solid blue;   /* border-left */
  border-start-start-radius: 8px;        /* top-left */
}

πŸ’» inset shorthand ​

css
/* ВмСсто top: 0; right: 0; bottom: 0; left: 0; */
.overlay { inset: 0; }

/* Как padding/margin β€” Π²Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒ / Π³ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒ */
.popup { inset: 10px 20px; }

/* ВсС Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ */
.modal { inset: 10px 20px 30px 40px; }

/* Частичный */
.fixed-bottom {
  inset: auto 0 0;  /* top:auto; right:0; bottom:0; left:0 */
}

πŸ’» content-visibility: auto ​

Π‘Ρ€Π°ΡƒΠ·Π΅Ρ€ пропускаСт Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³ элСмСнтов Π²Π½Π΅ viewport β€” ускоряСт Π·Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ Π΄Π»ΠΈΠ½Π½Ρ‹Ρ… страниц:

css
.article-card {
  content-visibility: auto;
  contain-intrinsic-size: 0 400px;  /* Π·Π°Π³Π»ΡƒΡˆΠΊΠ° Ρ€Π°Π·ΠΌΠ΅Ρ€Π° ΠΏΠΎΠΊΠ° Π½Π΅ отрисован */
}

Π”Π°Ρ‘Ρ‚ прирост ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π½Π° страницах с большим количСством ΠΊΠ°Ρ€Ρ‚ΠΎΡ‡Π΅ΠΊ/постов. НС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ для элСмСнтов с Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΠ΅ΠΉ Π² viewport.


πŸ’» field-sizing: content ​

input ΠΈ textarea автоматичСски растут ΠΏΠΎΠ΄ содСрТимоС:

css
textarea {
  field-sizing: content;    /* растёт ΠΏΠΎ тСксту */
  min-height: 3lh;          /* ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ 3 строки */
  max-height: 20lh;         /* максимум */
}

input[type="text"] {
  field-sizing: content;
  min-width: 10ch;
}

Π—Π°ΠΌΠ΅Π½Π° JavaScript auto-resize для textarea.


πŸ’» overscroll-behavior ​

ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‡Ρ‚ΠΎ происходит ΠΊΠΎΠ³Π΄Π° скролл достигаСт края:

css
/* МодальноС ΠΎΠΊΠ½ΠΎ Π½Π΅ скроллит body ΠΏΠΎΠ΄ собой */
.modal {
  overflow-y: auto;
  overscroll-behavior: contain;  /* скролл Π½Π΅ "ΠΏΠ΅Ρ€Π΅Ρ‚Π΅ΠΊΠ°Π΅Ρ‚" дальшС */
}

/* Π“ΠΎΡ€ΠΈΠ·ΠΎΠ½Ρ‚Π°Π»ΡŒΠ½Ρ‹ΠΉ слайдСр Π½Π΅ скроллит страницу */
.slider {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

/* ΠžΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ pull-to-refresh Π½Π° ΠΌΠΎΠ±ΠΈΠ»Π΅ */
body {
  overscroll-behavior-y: none;
}

πŸ’» scroll-snap ​

Нативный snap-скролл Π±Π΅Π· JavaScript:

css
.slider {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;   /* ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ snap ΠΏΠΎ X */
  gap: 1rem;
}

.slide {
  flex: 0 0 100%;
  scroll-snap-align: start;        /* start / center / end */
}

/* Π’Π΅Ρ€Ρ‚ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ snap */
.sections {
  height: 100dvh;
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
}

.section {
  height: 100dvh;
  scroll-snap-align: start;
}

πŸ’» overflow-anchor ​

ΠŸΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΠΏΡ€Ρ‹ΠΆΠΎΠΊ страницы ΠΊΠΎΠ³Π΄Π° Π²Ρ‹ΡˆΠ΅ загруТаСтся ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ сообщСния Π² Ρ‡Π°Ρ‚Π΅):

css
/* Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΎ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ */
.chat-messages {
  overflow-anchor: auto;   /* Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ Π΄Π΅Ρ€ΠΆΠΈΡ‚ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ скролла */
}

/* ΠžΡ‚ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ β€” Ссли Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€Ρ‹Π³Π°Ρ‚ΡŒ Π½Π°Π²Π΅Ρ€Ρ… ΠΏΡ€ΠΈ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ */
.feed {
  overflow-anchor: none;
}

⚠️ ΠŸΠΎΠ΄Π²ΠΎΠ΄Π½Ρ‹Π΅ ΠΊΠ°ΠΌΠ½ΠΈ ​

  • subgrid Π½Π΅ поддСрТиваСтся Π² Chrome < 117 β€” провСряй Ρ‡Π΅Ρ€Π΅Π· @supports
  • field-sizing: content β€” Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Chrome/Edge, Safari 2024+. Firefox β€” Π½Π΅Ρ‚
  • content-visibility: auto β€” Π½Π΅ примСняй ΠΊ элСмСнтам Π² viewport, Π±ΡƒΠ΄Π΅Ρ‚ ΠΌΠΈΠ³Π°Π½ΠΈΠ΅
  • scroll-snap-type: mandatory β€” агрСссивный, ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒΡΡ ΠΌΠ΅ΠΆΠ΄Ρƒ snap-Ρ‚ΠΎΡ‡ΠΊΠ°ΠΌΠΈ. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉ proximity
  • ЛогичСскиС свойства β€” Π½Π΅ смСшивай с физичСскими (margin-left + margin-inline-start) Π½Π° ΠΎΠ΄Π½ΠΎΠΌ элСмСнтС

Built with VitePress and ❀️