#статья дня в кратком переводе от подписчика
Ахмад шадид заметил что Facebook меняет border-radius своих карточек не настройкой media query как мы привыкли это делать, а с помощью логических выражений.
Погнали!
Проблема:
Допустим у нас есть компонент карточки с border-radius: 8px. Когда у карточки нет отступов а также она занимает всю ширину вьюпорта, нам надо изменить значение на border-radius: 0px.
Мы могли бы использовать CSS media query, чтобы просто сбрасывать значение, например так:
А что если в некоторых случаях нам снова нужен border-radius, например когда размер вью порта будет меньше 450px, нам придётся писать кучи медиа выражений:
Решение:
Пример использованный инженерами Facebook, имитирует следующую логику:
Чтобы реализовать эту логику в CSS, нам нужно сравнить два значения с помощью функций CSS.
Пройдемся по деталям реализации примера выше.
1. Функция max(), которая сравнивает 0px и вычисленное значение функции min(). Функция Max() выбирает наибольшее значение.
2. Функция min() сравнивает 8px и вычисленное значение из calc((100vw - 4px - 100%) * 9999). Это приведет к очень большому положительному или отрицательному числу.
3. 9999 - это просто большое число, чтобы мы могли точно установить одно из двух значений, значение 0px или 8px.
Число 9999 используется не потому что у него есть супер сила, а лишь для того, чтобы избежать крайнего случая (ниже)
Предположим, что ширина вью порта составляет 375px, а размер контейнера - 365px. Если подставить эти значения в уравнение, оно будет выглядеть так:
Из вышеизложенного, браузер выберет значение 6px. Мы этого не хотим. Вместо этого радиус должен быть либо 0px, либо 8px. По этому мы умножаем результат на большое число, которое с меньшей вероятностью будет использоваться в CSS, например 9999.
Исходя из этого, браузер выберет 8px из функции min(), а затем такое же значение из функции max().
Возьмем пример, основанный на первом сценарии. У нас есть область просмотра шириной 1440px, а карточка находится в контейнере 700px.
Умножение полученного значения на 9999 даст 7359264. В этом случае CSS будет выглядеть для браузера следующим образом:
Обе функции min() и max() в примере выше выберут значение в 8px.
Это первый пример использования этого сценария.
А что будет, когда карточка займёт всю ширину вьюпорта?
Умножение значения на 9999 даст -39996 пикселей, что является отрицательным. Для браузера это будет выглядеть так:
А теперь самое интересное! Браузеру нужно задать два вопроса:
Какое значение меньше? 8px или -39996px? Результат -39996 пикселей.
Какое значение больше? 0px или -39996px? Результат - 0 пикселей.
Круто? До сих пор удивляюсь столь умному использованию функций сравнения CSS.
Полная статья, а также codepen прилагаются.
#borderradius #css #viewport
Ахмад шадид заметил что Facebook меняет border-radius своих карточек не настройкой media query как мы привыкли это делать, а с помощью логических выражений.
Погнали!
Проблема:
Допустим у нас есть компонент карточки с border-radius: 8px. Когда у карточки нет отступов а также она занимает всю ширину вьюпорта, нам надо изменить значение на border-radius: 0px.
Мы могли бы использовать CSS media query, чтобы просто сбрасывать значение, например так:
@media (min-width: 700px) {
.card {
border-radius: 8px;
}
}
А что если в некоторых случаях нам снова нужен border-radius, например когда размер вью порта будет меньше 450px, нам придётся писать кучи медиа выражений:
@media (max-width: 450px) {
.card--rounded {
border-radius: 8px;
}
}
Решение:
Пример использованный инженерами Facebook, имитирует следующую логику:
if (ширинаКарточки >= ШиринеВьюПорта) {
radius = 0;
} else {
radius = 8px;
}
Чтобы реализовать эту логику в CSS, нам нужно сравнить два значения с помощью функций CSS.
.card {
border-radius: max(0px, min(8px, calc((100vw - 4px - 100%)
* 9999)));
}
Пройдемся по деталям реализации примера выше.
1. Функция max(), которая сравнивает 0px и вычисленное значение функции min(). Функция Max() выбирает наибольшее значение.
2. Функция min() сравнивает 8px и вычисленное значение из calc((100vw - 4px - 100%) * 9999). Это приведет к очень большому положительному или отрицательному числу.
3. 9999 - это просто большое число, чтобы мы могли точно установить одно из двух значений, значение 0px или 8px.
Число 9999 используется не потому что у него есть супер сила, а лишь для того, чтобы избежать крайнего случая (ниже)
Предположим, что ширина вью порта составляет 375px, а размер контейнера - 365px. Если подставить эти значения в уравнение, оно будет выглядеть так:
.card {
border-radius: max(0px, min(8px, calc(375px - 4px - 365px)));
/* Превратится в */
border-radius: max(0px, min(8px, 6px));
}
Из вышеизложенного, браузер выберет значение 6px. Мы этого не хотим. Вместо этого радиус должен быть либо 0px, либо 8px. По этому мы умножаем результат на большое число, которое с меньшей вероятностью будет использоваться в CSS, например 9999.
.card {
border-radius: max(0px, min(8px, calc((375px - 4px - 365px) * 9999)));
/* Превратится в */
border-radius: max(0px, min(8px, 59994px));
}
Исходя из этого, браузер выберет 8px из функции min(), а затем такое же значение из функции max().
Возьмем пример, основанный на первом сценарии. У нас есть область просмотра шириной 1440px, а карточка находится в контейнере 700px.
.card {
border-radius: max(0px, min(8px, calc((100vw - 4px - 100%) * 9999)));
/* В нашем случае это: */
border-radius: max(0px, min(8px, calc((1440px - 4px - 700px) * 9999)));
}
Умножение полученного значения на 9999 даст 7359264. В этом случае CSS будет выглядеть для браузера следующим образом:
.card {
border-radius: max(0px, min(8px, 7359264px));
}
Обе функции min() и max() в примере выше выберут значение в 8px.
.card {
border-radius: 8px;
}
Это первый пример использования этого сценария.
А что будет, когда карточка займёт всю ширину вьюпорта?
.card {
border-radius: max(0px, min(8px, calc((100vw - 4px - 100%) * 9999)));
/* А в нашем случае это: */
border-radius: max(0px, min(8px, calc((375px - 4px - 375px) * 9999)));
}
Умножение значения на 9999 даст -39996 пикселей, что является отрицательным. Для браузера это будет выглядеть так:
.card {
border-radius: max(0px, min(8px, -39996px));
}
А теперь самое интересное! Браузеру нужно задать два вопроса:
Какое значение меньше? 8px или -39996px? Результат -39996 пикселей.
Какое значение больше? 0px или -39996px? Результат - 0 пикселей.
Круто? До сих пор удивляюсь столь умному использованию функций сравнения CSS.
Полная статья, а также codepen прилагаются.
#borderradius #css #viewport
Ishadeed
Conditional Border Radius In CSS
How to use CSS comparison functions to create a conditional border radius
#заметка дня
Итак, что же меня восхищает в волшебном значении border-radius равному 9999px?
Всё очень просто и забавно одновременно: border-radius: 9999px построит вам прямоугольник со скруглёнными углами. В случае квадрата это будет, очевидно, круг.
Вот issue из обсуждений спецификации CSS WG: https://www.w3.org/Style/CSS/Tracker/issues/29
Сам автор issue говорит, что безпол-литра картинок там не разобраться. Cut the crap, они пошли по третьему варианту: https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
Там в целом геометрия эллипсов, потому описание формулы такое странное и учитываются все углы, но давайте просто посчитаем, что же получится для значения в 10000px (проще считать) и прямоугольника размером 320x240px, углы начинаем с верхнего левого (Top Left):
TL: 320/20000 vs 240/20000
TR: 320/20000 vs 240/20000
BR: 320/20000 vs 240/20000
BL: 320/20000 vs 240/20000
0.016 vs 0.012 в каждом случае
Итого, 0.012 — минимальное значение коэффициента приведения радиуса.
10000 * 0.012 = 120.
Половина высоты, выходит. Проверяем себя: https://codepen.io/alinaki/pen/jOxRwJJ
Вариант, когда значения радиуса индивидуальны, рассмотрен там же в спецификации.
Во Flutter используется геометрия кривых и понять это пусть всё ещё проще, чем структуру исходного кода Chromium, но всё равно сложно. Тем не менее, имеются упоминания, что радиусы приводятся к минимальному значению размерности.
И да, 9999px это совсем не то же, что 50%, опять же — смотрите спецификацию, там эллипсы. Но в случае квадрата — и там и там будет круг.
#geometry #borderradius #css #flutter
Итак, что же меня восхищает в волшебном значении border-radius равному 9999px?
Всё очень просто и забавно одновременно: border-radius: 9999px построит вам прямоугольник со скруглёнными углами. В случае квадрата это будет, очевидно, круг.
Вот issue из обсуждений спецификации CSS WG: https://www.w3.org/Style/CSS/Tracker/issues/29
Сам автор issue говорит, что без
Там в целом геометрия эллипсов, потому описание формулы такое странное и учитываются все углы, но давайте просто посчитаем, что же получится для значения в 10000px (проще считать) и прямоугольника размером 320x240px, углы начинаем с верхнего левого (Top Left):
TL: 320/20000 vs 240/20000
TR: 320/20000 vs 240/20000
BR: 320/20000 vs 240/20000
BL: 320/20000 vs 240/20000
0.016 vs 0.012 в каждом случае
Итого, 0.012 — минимальное значение коэффициента приведения радиуса.
10000 * 0.012 = 120.
Половина высоты, выходит. Проверяем себя: https://codepen.io/alinaki/pen/jOxRwJJ
Вариант, когда значения радиуса индивидуальны, рассмотрен там же в спецификации.
Во Flutter используется геометрия кривых и понять это пусть всё ещё проще, чем структуру исходного кода Chromium, но всё равно сложно. Тем не менее, имеются упоминания, что радиусы приводятся к минимальному значению размерности.
И да, 9999px это совсем не то же, что 50%, опять же — смотрите спецификацию, там эллипсы. Но в случае квадрата — и там и там будет круг.
#geometry #borderradius #css #flutter
👍5🤯3