June 26, 2020

Цікаві CSS-знахідки в новому дизайні Twitter

26.06.20. Час прочитання - 10 хв

Новий дизайн Twitter з'явився майже рік тому. В CSS-коді Twitter можна знайти багато цікавого: дещо виглядає просто чудово, а дещо доволі дивно. Давайте разом проаналізуємо та розберемо код.

Співвідношення сторін аватарів користувачів

У новій версії з'явилась цікава реалізація аватара користувача на сторінці профілю. Розробники використали CSS-техніку збереження співвідношення сторін елемента.

ацію аватара користувача на сторінці профілю. У цій реалізації використовується CSS-техніка збереження співвідношення сторін елемента.

Аватар користувача на сторінці профілю

Нижче показуємо HTML- і CSS-код, що ілюструє реалізацію аватара.

<a href="#" class="avatar"> <div class="avatar-aspect-ratio"></div> <img alt="" src="me.jpg"> </a> .avatar { position: relative; width: 25%; display: block; } .avatar-aspect-ratio { width: 100%; padding-bottom: 100%; } .avatar img { position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%; }

Техніка збереження співвідношення сторін елемента працює завдяки тому, що, коли у елемента є вертикальний внутрішній відступ (властивість padding-bottom або padding-top), відступ залежить від ширини елемента. Гляньте на наступний приклад:

.element { width: 250px; padding-bottom: 100%; }

Обчислення значення padding-bottom дорівнює 250px. Це означає, що у нас є ідеальний квадрат. Команда Twitter використовувала таку ж техніку, але в застосуванні до елементу <img>, який, по відношенню до батьківського елементу, позиціонується абсолютно. Чому? Ось причина.

Коли зображення не позиціоноване абсолютно, аватар буде виглядати так, як на малюнку. Його потрібно позиціонувати з використанням значення 100% для ширини і висоти. При такому підході його розмір буде встановлений відповідно до розміру елемента-обгортки.

Тепер, коли ми розібралися з ідеєю, що лежить в основі цього рішення, повернемося до того, як ця ідея реалізована в Twitter.

Властивість width: 25% засновано на ширині елемента-обгортки. Чому була обрана саме ця методика. Але якщо краще вивчити CSS-код, то ви звернете увагу на те, що цей же компонент використовується в модальному вікні Edit Profile. Правда, елемент тут має менший розмір через використання наступного стилю:

.avatar { max-width: 8rem; /* 112px замість 150px (25%) */ }

Управління шириною зображення

Верхній зовнішній відступ, заданий у відсотках

Для того, щоб аватар користувача перекривав фото, яке перебуває у верхній частині сторінки профілю, використовується негативний зовнішній відступ, заданий у відсотках:

.avatar { margin-top: -18%; }

Правда, в модальному вікні Edit Profile для налаштування верхнього зовнішнього відступу використовується вже конструкція margin-top: -3rem. Зверніть увагу на те, що відступ в модальному вікні задається з використанням одиниць вимірювання rem. Ті ж одиниці вимірювання застосовуються і для налаштування властивості max-width.

Дивне використання CSS-функції calc ()

Для стилізації деяких кнопок використовується наступний CSS-код:

.button { min-width: calc(45.08px) }

Навіщо передавати функції calc () єдине значення? Може, число 45.08 хотіли округлити? Але воно за такого підходу не округляється до 45. Загалом ширина кнопки дуже мала. При перекладі додатку на RTL-мову, на кшталт арабського, вона точно буде надто маленькою.

Занадто маленька кнопка

Функція calc () з'являється у вбудованому CSS-коді. Тому це результат динамічної стилізації кнопки засобами React.

Змішування CSS-фонів і HTML-зображень

У багатьох місцях сайту присутнє змішування фонових зображень, що задаються засобами CSS, і HTML-зображень. Гляньте на наступний приклад:

<div style="background-image: url(me.jpg);"></div> <img alt="" src="me.jpg">

Змішування фону присутнє в профілі користувача і в компоненті, що використовується при формуванні сіткового макета. Цікаво те, що властивість opacity елемента <img> задано в 0. Джерелом активного зображення є властивість background-image. Крім того, тут використовується і властивість background-size: cover, яка дозволяє уникнути спотворення зображення.

Якщо зробити все навпаки, тобто показати елемент <img> і приховати CSS-фон, то порівнюючи вони виглядатимуть ось так:

Зліва - варіант, в якому використовується фонове зображення, а справа - варіант, в якому застосовується HTML-зображення

Скидання стилів

Розробники застосували один патерн, який полягає в постійному використанні CSS-класу, який додається до елементів <div>. Ось відповідний CSS-код:

.css-1dbjc4n { align-items: stretch; border: 0 solid black; box-sizing: border-box; display: flex; flex-basis: auto; flex-direction: column; flex-shrink: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; min-height: 0px; min-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; position: relative; z-index: 0; }

Цей стиль застосовується буквально до кожного елементу <div>, що знаходиться на сторінці. Чому? Хіба тут недостатньо скидання CSS-стилів?

Деякі з вищеописаних стилів цілком зрозумілі, на кшталт min-width: 0, оскільки тут простежується певний зв'язок з Flexbox. Але як щодо внутрішніх відступів, зовнішніх відступів, меж? Чому у якогось елемента <div> треба скидати стилі, з огляду на те, що у цього елемента немає відповідних властивостей?

Flexbox і min-width: 0

По дефолту властивість min-width є auto, яка є рівною нулю. Коли щось виводиться як flex-елемент, значення його властивості min-width дорівнює розміру його вмісту. Дозвіл такої поведінки може порушити макет в тому випадку, якщо вміст елемента більший, ніж він сам.

Для того щоб уникнути виникнення цієї проблеми, потрібно скидати властивість min-width для нащадків flex-елементів.

Flex-елемент і Flexbox-обгортка

Макет, наведений вище, показує, що може статися в тому випадку, якщо вміст flex-елемента виявиться занадто довгим. Зверніть увагу на те, що текст виходить за межі елемента-обгортки. А ось що виходить при використанні властивості min-width: 0.

Вміст не виходить за межі flex-елемента

Використання властивості position: sticky

В правій бічній панелі Twitter (там, де виводяться медіа тренди і рекомендації, що стосуються користувачів, на яких можна підписатися) використовується властивість position: sticky. Дуже цікаво організована робота зі значеннями властивостей bottom і top під час прокручування. Значення, встановлені за замовчуванням, виглядають так:

.sidebar { position: sticky; width: 350px; bottom: -470.5px; }

Коли сторінку прокручують вниз, властивість bottom замінюється на властивість top: -480.5px. Мабуть, дизайнери вирішили так для того, щоб дозволити користувачеві спочатку дійти до кінця бічної панелі, бо властивість top додається вже після цього.

Елементи-роздільники

В дизайні Twitter в багатьох місцях використовуються елементи-роздільники. Все це — flex-елементи, ширина яких встановлена з використанням властивості flex-basis.

Елементи-роздільники

У першому елементі, наведеному на зображенні, при налаштуванні елемента-роздільника використовується властивість flex-grow: 1. У другому використовується фіксована ширина, задана в пікселях.

Твіт

Вище показаний твіт. На перший погляд може здатися, що перед нами елемент <p> або <span>, в який доданий текст. Але, як виявилося, кожен смайлик представлений окремим тегом <span>, а якщо текст знаходиться між двома такими елементами, він теж оформляється у вигляді тега <span>.

Оформлення тексту твіта

Смайлик — це <span>, в якому є елемент <div>, в <div> містяться два зображення. Одне — це CSS-фон, друге — HTML-зображення.

Оскільки перше речення обгорнуте тегом <span>, між ним і елементами одного з ним рівня повинні бути роздільники. Дизайнери додали перехід на новий рядок на початку другого речення для того щоб розділити речення.

Використання обчислюваних значень для поділу елементів

При виконанні пошуку в Twitter, або при відкритті сторінки профілю, можна побачити кнопку Назад. До цієї кнопки застосований стиль margin-left: -4px, що задає негативний зовнішній лівий відступ. Нас зацікавила процедура обчислення цього значення.

.back-button { margin-left: calc(5px + (-1 * (39px - 1.5em)) / 2); }

Вищенаведені обчислення призводять до отримання значення -4px. Чому б не поставити просто -4px? Чи не краще це в цьому випадку, ніж застосування функції calc ()?

Ширина навігаційних посилань

З панеллю навігаційних посилань теж є своя особливість, при наведенні на елементи мишкою, їх ширина стає рівною їх вмісту. Чому б не зробити так, щоб значок і мітка займали всю ширину навігаційного елемента.

І ще увагу привернуло використання властивості flex-direction: column для кожного елемента навігаційної панелі. Чому? Чи потрібно це в ситуації, коли тут використовується лише один дочірній елемент?

Зовнішній відступ, що додається «про всяк випадок»

Відступ, про який йде мова, є присутнім в дизайні для запобігання небажаної поведінки макета сторінки. Існує два приклади використання зовнішніх відступів, що додаються до елементів, так би мовити, «на всякий випадок». Подивимося на них.

Відступи, що додаються до елементів «про всяк випадок». Зліва - звичайний вміст елемента. Праворуч - вміст, який помітно довший за звичайний

Зверніть увагу на те, що відбувається в тому випадку, коли вміст елемента помітно довший, ніж його звичайний вміст. А саме, тут відбувається наступне:

1. Текст обрізається.
2. Між елементами присутній зовнішній відступ.

Зовнішній відступ грає роль місцезаповнювача, який не дає елементу зайняти весь простір. Якщо вчасно це врахувати, можна уникнути несподіваних проблем, які можуть виникнути в процесі роботи проєкту. Рекомендується завжди тестувати макети сторінок з використанням вмісту, довжина якого перевищує якусь «звичайну» довжину.

Модальні вікна в областях перегляду маленької висоти

На зображенні модальне вікно редагування профілю. Виявилося, що при певній висоті області перегляду кнопка Save такого вікна недоступна. Ось як це виглядає.

Недоступна кнопка Savе

Оскільки модальне вікно не підтримує прокрутку, до кнопки Save дістатися не вдалося. А ось вікно, що використовується для управління зовнішнім виглядом елементів, підтримує динамічну зміну висоти і прокручування.

Вікно, що підтримує динамічну зміну висоти

Чому одне вікно підтримує скрол, а інше — ні? Цікаво знати, яке з них, на думку дизайнерів Twitter, важливіше? Які Ваші враження після аналізу дизайну та коду Twitter? Діліться відгуками та думками у коментарях під статтею.