Рома Ахмадуллин
Дром
Дром — автомобильный классифайд
Дока — добрая энциклопедия про веб
Responsive Web Design
.card {
display: flex;
.image {
width: 150px;
height: 100%;
}
}
@media (width <= 375px) {
.card {
flex-direction: column;
.image {
width: 100%;
height: 100px;
}
}
}
.card {
display: flex;
.image {
width: 150px;
height: 100%;
}
}
@media (width <= 375px) {
.card {
flex-direction: column;
.image {
width: 100%;
height: 100px;
}
}
}
.card {
display: flex;
.image {
width: 150px;
height: 100%;
}
}
@media (width <= 375px) {
.card {
flex-direction: column;
.image {
width: 100%;
height: 100px;
}
}
}
Механизм, позволяющий применять стили к элементу в зависимости от размеров его контейнера.
<div class="container">
<div class="element"></div>
</div>
.container {
container-type: inline-size;
}
.element {
color: blue;
}
@container (width <= 200px) {
.element {
color: green;
}
}
.container {
container-type: inline-size;
}
.element {
color: blue;
}
@container (width <= 200px) {
.element {
color: green;
}
}
.container {
container-type: inline-size;
}
.element {
color: blue;
}
@container (width <= 200px) {
.element {
color: green;
}
}
.container {
container-type: inline-size;
}
.element {
color: blue;
}
@container (width <= 200px) {
.element {
color: green;
}
}
.container {
container-name: card;
container-type: inline-size;
}
.element {
color: blue;
}
@container card (width <= 200px) {
.element {
color: green;
}
}
.container {
container-name: card;
container-type: inline-size;
}
.element {
color: blue;
}
@container card (width <= 200px) {
.element {
color: green;
}
}
.container {
container-name: card;
container-type: inline-size;
}
.element {
color: blue;
}
@container card (width <= 200px) {
.element {
color: green;
}
}
.container {
container-name: card;
container-type: inline-size;
container: card / inline-size;
}
.element {
color: blue;
}
@container card (width <= 200px) {
.element {
color: green;
}
}
.container {
container-name: card;
container-type: inline-size;
container: card / inline-size;
}
.element {
color: blue;
}
@container card (width <= 200px) {
.element {
color: green;
}
}
container-typenormal — дефолтное значениеcontainer-typenormal — дефолтное значениеinline-size — следим за inline осьюcontainer-typenormal — дефолтное значениеinline-size — следим за inline осьюsize — следим за inline и block осямиcontainer-typenormal — дефолтное значениеinline-size — следим за inline осьюsize — следим за inline и block осями
<article class="card">
<div class="card-content">
<img src="pic.jpg" class="image">
<div class="text-container">
<h3 class="title"></h3>
<p class="text"></p>
<a href="site.com" class="link"></a>
</div>
</div>
</article>
.card {
container: card / inline-size;
}
.card-content {
display: flex;
gap: 20px;
padding: 10px;
font-size: 16px;
}
@container card (width <= 200px) {
.card-content {
flex-direction: column;
gap: 10px;
font-size: 18px;
}
}
.container {
display: block;
border: 2px solid white;
padding: 20px;
}
container-type ➡️ contain
Rachel Andrew: Статья про contain
.container {
container-type: inline-size;
border: 2px solid white;
padding: 20px;
}
.element {
background: green;
}
@container (width <= 300px) {
.element {
background: yellow;
}
}
cqw — 1% ширины контейнера
cqh — 1% высоты контейнера
cqw — 1% ширины контейнера
cqh — 1% высоты контейнера
cqi — 1% inline размера контейнера
cqb — 1% block размера контейнера
cqw — 1% ширины контейнера
cqh — 1% высоты контейнера
cqi — 1% inline размера контейнера
cqb — 1% block размера контейнера
cqmin — минимальное значение из cqi и cqb
cqmax — максимальное значение из cqi и cqb
cqw — 1% ширины контейнера
cqh — 1% высоты контейнера
cqi — 1% inline размера контейнера
cqb — 1% block размера контейнера
cqmin — минимальное значение из cqi и cqb
cqmax — максимальное значение из cqi и cqb
Интерактивный гайд по Container Queires
.text {
font-size: 30px;
}
@container card (width <= 600px) {
.text {
font-size: 20px;
}
}
@container card (width <= 400px) {
.text {
font-size: 18px;
}
}
clamp()
Позволяет ограничивать диапазон изменения некоего значения, задавая его нижний и верхний пределы.
clamp(min, preferred, max)
clamp(min, preferred, max)
clamp(min, preferred, max)
clamp(min, preferred, max)
clamp(18px, 24px, 30px)
clamp(1rem, 1.5rem, 2rem)
clamp(1rem, 0.5rem + 3cqw, 2rem)
clamp(1rem, 0.5rem + 3cqw, 2rem)
clamp(1rem, 0.5rem + 3cqw, 2rem)
clamp(1rem, 0.5rem + 3cqw, 2rem)
Татьяна Фокина: Fluid Typography and CSS clamp()
Механизм, позволяющий применять стили к элементу в зависимости от значений вычисленных CSS-свойств его контейнера.
.container {
container-type: normal;
container-name: card;
}
.element {
color: blue;
}
@container card style(--feature: true) {
.element {
color: green;
}
}
.container {
container-type: normal;
container-name: card;
}
.element {
color: blue;
}
@container card style(--feature: true) {
.element {
color: green;
}
}
.container {
container-type: normal;
container-name: card;
}
.element {
color: blue;
}
@container card style(--feature: true) {
.element {
color: green;
}
}
.container {
container-type: normal;
container-name: card;
}
.element {
color: blue;
}
@container card style(--feature: true) {
.element {
color: green;
}
}
.container {
container-type: normal;
container-name: card;
}
.element {
color: blue;
}
@container card style(--feature: true) {
.element {
color: green;
}
}
<div class="card">
...
</div>
<div class="card">
...
</div>
<div class="card">
...
</div>
<div class="card" style="--label: 'новый';">
...
</div>
<div class="card">
...
</div>
<div class="card">
...
</div>
.card {
container-name: card;
}
@container card style(--label: 'новый') {
.card-content::after {
content: 'новый';
background-color: green;
}
}
<div class="weather-card" style="--snow: true;">
...
</div>
<div class="weather-card" style="--cloudy: true;">
...
</div>
<div class="weather-card" style="--cloudy: true; --sunny: true;">
...
</div>
<div class="weather-card" style="--sunny: true;">
...
</div>
@container style(--snow: true) {
/* меняем цвет фона и иконку */
}
@container style(--cloudy: true) {
...
}
@container style(--sunny: true) {
...
}
@container style(--sunny: true) and style(--cloudy: true) {
...
}
@container style(--snow: true) {
/* меняем цвет фона и иконку */
}
@container style(--cloudy: true) {
...
}
@container style(--sunny: true) {
...
}
@container style(--sunny: true) and style(--cloudy: true) {
...
}
.card {
container: card / inline-size;
}
.card-layout {
/* дефолтные стили */
}
@container card (width <= 414px) and style(--vertical: true) {
.card-layout {
/* стили для вертикальной карточки */
}
}
.card {
container: card / inline-size;
}
.card-layout {
/* дефолтные стили */
}
@container card (width <= 414px) and style(--vertical: true) {
.card-layout {
/* стили для вертикальной карточки */
}
}
.parent > hr {
height: 5px;
}
.parent hr ~ p {
color: green;
}
.parent hr + p {
color: yellow;
}
/* hr непосредственно внутри parent */
.parent > hr {
height: 5px;
}
.parent hr ~ p {
color: green;
}
.parent hr + p {
color: yellow;
}
/* hr непосредственно внутри parent */
.parent > hr {
height: 5px;
}
/* все параграфы после hr */
.parent hr ~ p {
color: green;
}
.parent hr + p {
color: yellow;
}
/* hr непосредственно внутри parent */
.parent > hr {
height: 5px;
}
/* все параграфы после hr */
.parent hr ~ p {
color: green;
}
/* первый параграф после hr */
.parent hr + p {
color: yellow;
}
/* hr непосредственно внутри parent */
.parent > hr {
height: 5px;
}
/* все параграфы после hr */
.parent hr ~ p {
color: green;
}
/* первый параграф после hr */
.parent hr + p {
color: yellow;
}
/* hr непосредственно внутри parent */
.parent > hr {
height: 5px;
}
/* все параграфы после hr */
.parent hr ~ p {
color: green;
}
/* первый параграф после hr */
.parent hr + p {
color: yellow;
}
:has():has()
Позволяет стилизовать родительский элемент при наличии конкретного дочернего элемента.
.parent:has(.child) {
/* стили для родителя */
}
.parent:has(.child) {
/* стили для родителя */
}
.parent:has(.child) {
/* стили для родителя */
}
<div class="card">
...
</div>
<div class="card with-image">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card.with-image {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card with-image">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card.with-image {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card with-image">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card.with-image {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card with-image">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card.with-image {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card with-image">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card.with-image {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card:has(img) {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card:has(img) {
/* стили для кейса с карточкой */
}
<div class="card">
...
</div>
<div class="card">
<img src="pic.jpg">
...
</div>
.card {
/* дефолтные стили */
}
.card:has(img) {
/* стили для кейса с карточкой */
}
.file {
background-image: var(--bg);
}
.file:has([href$=".pdf"]) {
--bg: 'icon-pdf.svg';
}
.file:has([href$=".ppt"]) {
--bg: 'icon-ppt.svg';
}
.file:has([href$=".docx"]) {
--bg: 'icon-docx.svg';
}
.file {
background-image: var(--bg);
}
.file:has([href$=".pdf"]) {
--bg: 'icon-pdf.svg';
}
.file:has([href$=".ppt"]) {
--bg: 'icon-ppt.svg';
}
.file:has([href$=".docx"]) {
--bg: 'icon-docx.svg';
}
.file {
background-image: var(--bg);
}
.file:has([href$=".pdf"]) {
--bg: 'icon-pdf.svg';
}
.file:has([href$=".ppt"]) {
--bg: 'icon-ppt.svg';
}
.file:has([href$=".docx"]) {
--bg: 'icon-docx.svg';
}
Интерактивный гайд по :has()
.card {
position: relative;
padding: 20px;
padding-right: 70px;
}
.icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
html[dir="ltr"] .card {
position: relative;
padding: 20px;
padding-right: 70px;
}
html[dir="ltr"] .icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
html[dir="rtl"] .card {
position: relative;
padding: 20px;
padding-left: 70px;
}
html[dir="rtl"] .icon {
position: absolute;
top: 20px;
left: 20px;
width: 40px;
height: 40px;
}
html[dir="ltr"] .card {
position: relative;
padding: 20px;
padding-right: 70px;
}
html[dir="ltr"] .icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
html[dir="rtl"] .card {
position: relative;
padding: 20px;
padding-left: 70px;
}
html[dir="rtl"] .icon {
position: absolute;
top: 20px;
left: 20px;
width: 40px;
height: 40px;
}
html[dir="ltr"] .card {
position: relative;
padding: 20px;
padding-right: 70px;
}
html[dir="ltr"] .icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
html[dir="rtl"] .card {
position: relative;
padding: 20px;
padding-left: 70px;
}
html[dir="rtl"] .icon {
position: absolute;
top: 20px;
left: 20px;
width: 40px;
height: 40px;
}
Позволяют описывать размеры и отступы на основе логических значений — основанных на направлении текста и режима письма.
block — направление расположения блоков контента на странице
block — направление расположения блоков контента на странице
inline — направление расположения контента внутри блока
block — направление расположения блоков контента на странице
inline — направление расположения контента внутри блока
size — альтернатива width и height
block — направление расположения блоков контента на странице
inline — направление расположения контента внутри блока
size — альтернатива width и height
insetwidthheightmarginpaddingborderborder-radius
.card {
position: relative;
padding: 20px;
padding-right: 70px;
}
.icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
.card {
position: relative;
padding: 20px;
padding-right: 70px;
}
.icon {
position: absolute;
top: 20px;
right: 20px;
width: 40px;
height: 40px;
}
.card {
position: relative;
padding: 20px;
padding-inline-end: 70px;
}
.icon {
position: absolute;
inset-block-start: 20px;
inset-inline-end: 20px;
inline-size: 40px;
block-size: 40px;
}
.card {
position: relative;
padding: 20px;
padding-inline-end: 70px;
}
.icon {
position: absolute;
inset-block-start: 20px;
inset-inline-end: 20px;
inline-size: 40px;
block-size: 40px;
}
Дока: Логические свойства CSS
Определяет, как элемент может менять свой размер
и позиционироваться на странице относительно одного или нескольких якорей.
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}
.anchor {
anchor-name: --my-anchor;
}
.tooltip {
position: fixed;
position-anchor: --my-anchor;
position-area: top;
position-try-fallbacks: flip-block;
}
.tooltip::before {
content: '▼';
position: absolute;
top: 100%;
}
.tooltip {
...
position-try-fallbacks: flip-block;
container-type: anchored;
}
.tooltip::before {
content: '▼';
position: absolute;
top: 100%;
}
@container anchored(fallback: flip-block) {
.tooltip::before {
content: '▲';
top: auto;
bottom: 100%;
}
}
.tooltip {
...
position-try-fallbacks: flip-block;
container-type: anchored;
}
.tooltip::before {
content: '▼';
position: absolute;
top: 100%;
}
@container anchored(fallback: flip-block) {
.tooltip::before {
content: '▲';
top: auto;
bottom: 100%;
}
}
.tooltip {
...
position-try-fallbacks: flip-block;
container-type: anchored;
}
.tooltip::before {
content: '▼';
position: absolute;
top: 100%;
}
@container anchored(fallback: flip-block) {
.tooltip::before {
content: '▲';
top: auto;
bottom: 100%;
}
}
.tooltip {
...
position-try-fallbacks: flip-block;
container-type: anchored;
}
.tooltip::before {
content: '▼';
position: absolute;
top: 100%;
}
@container anchored(fallback: flip-block) {
.tooltip::before {
content: '▲';
top: auto;
bottom: 100%;
}
}
Рома Ахмадуллин: CSS Anchor Positioning
@media (prefers-color-scheme)
.page {
background: white;
color: black;
}
@media (prefers-color-scheme: dark) {
.page {
background: black;
color: white;
}
}
.page {
background: white;
color: black;
}
@media (prefers-color-scheme: dark) {
.page {
background: black;
color: white;
}
}
.page {
background: white;
color: black;
}
@media (prefers-color-scheme: dark) {
.page {
background: black;
color: white;
}
}
@media (пользовательские предпочтения)prefers-color-scheme — светлая / тёмная темаprefers-contrast — повышенная / пониженная контрастность@media (пользовательские предпочтения)prefers-color-scheme — светлая / тёмная темаprefers-contrast — повышенная / пониженная контрастностьprefers-reduced-motion — наличие анимаций@media (пользовательские предпочтения)prefers-color-scheme — светлая / тёмная темаprefers-contrast — повышенная / пониженная контрастностьprefers-reduced-motion — наличие анимацийprefers-reduced-transparency — наличие прозрачности@media (пользовательские предпочтения)prefers-color-scheme — светлая / тёмная темаprefers-contrast — повышенная / пониженная контрастностьprefers-reduced-motion — наличие анимацийprefers-reduced-transparency — наличие прозрачности
selector {
/* дефолтные стили */
}
@media (prefers-...) {
selector {
/* стили, учитывающие предпочтения */
}
}
Татьяна Фокина: CSS-медиафичи для улучшения доступности
| Адаптив | CSS-cвойства |
|---|---|
| вьюпорт |
@media(size)
|
| контент |
flex,
grid,
:has()
|
| контейнер |
@container,
clamp()
|
| предпочтения пользователя |
@media(prefers-...)
|
| окружающая среда |
logical properties,
anchor positioning
|