[Перевод] Интересные CSS-находки в новом дизайне Facebook
Я любопытен. Мне всегда интересно открывать инструменты разработчика браузера и разбираться с тем, как сделан какой-нибудь сайт, на который я заглянул. Этот материал представляет собой мой первый рассказ о таких вот изысканиях. Дело в том, что я обнаружил некоторые интересные примеры использования CSS (по крайней мере, они показались интересными мне), о которых мне захотелось рассказать.
Речь идёт о CSS-находках в новом дизайне Facebook. Этот дизайн появился сравнительно недавно. Я его увидел пару недель назад. Сначала все элементы интерфейса казались мне необычно большими, но я привык к ним буквально за несколько дней. Здесь я расскажу обо всём том интересном, что я нашёл в дизайне Facebook.
Использование SVG-графики в аватарах
Аватары
SVG-графика используется для изображений-аватаров, таких, как фото профиля, фото на страницах пользователя или в группах.
Вот HTML-код:
Когда я это увидел, я задался вопросом о том, почему используется именно такой подход. У меня на этот вопрос есть несколько ответов:
- У аватара должна быть внутренняя рамка, имеющая полупрозрачный чёрный цвет (10%). Это нужно для того чтобы светлые аватары выглядели бы как круглые изображения. Причём, даже в том случае, если это — полностью белые изображения.
- К HTML-элементу
нельзя добавить внутреннюю тень (
box-shadow
) с использованием ключевого словаinset
. SVG используется для решения этой задачи. - Для того чтобы изображение имело бы круглую форму, используются SVG-элементы
и
.
Как я уже сказал, рамки внутри аватара весьма полезны для светлых изображений. Вот макет, который иллюстрирует эту идею.
Аватары
Внутренняя рамка настроена с помощью следующего CSS-кода:
circle,
rect {
stroke-width: 2;
stroke: rgba(0, 0, 0, 0.1);
fill: none;
}
Если изображение является квадратным — используется фигура rect
:
Позвольте мне немного пояснить вышеприведённый рисунок. Это — фрагмент раздела, в котором находятся запросы на добавление в друзья, появляющиеся на домашней странице. Перед нами — некая сетка со сведениями о людях. У этой сетки должен быть левый внешний отступ. Я обычно добавляю к элементам подобные границы так: Зачем дизайнеры поступили именно так? У меня есть несколько догадок: Взгляните на эти четыре иконки. Иконка со значком «плюс» и иконка со стрелкой созданы с использованием элемента Если щёлкнуть по последней иконке, то стрелка будет перекрашена в синий цвет. «Как здесь меняется цвет, ведь стрелка — это обычное изображение?», — спросил я себя. Может, при наведении указателя мыши на иконку одно изображение просто меняется на другое? Нет, всё не так. Я выяснил, что для изменения цвета значка на иконке используется CSS-фильтр: То же самое используется и при создании значка для верифицированных аккаунтов. Нечто подобное применяется и для ссылок из профиля пользователя: Если вам интересно узнать о том, как с помощью CSS-фильтров окрасить в любой цвет изображение, выполненное чёрным цветом, — взгляните на этот ответ на Stack Overflow. Там же можно найти инструмент для создания CSS-фильтров. Кроме того — взгляните на этот твит. У главного заголовка окна имеется тень. Можно предположить, что она создана с использованием CSS-свойства Я загрузил использованное здесь изображение, что позволяет рассмотреть его поближе. Это — изображение размером 2×14 пикселей, которое, для создания эффекта тени, многократно повторяется. В формировании эффекта тени участвует не только изображение, но и специальный элемент Сотрудник Facebook сообщил о том, что изображение здесь было использовано из соображений производительности. Тут интересно то, что столь маленькая тень способна привести к проблемам со скоростью работы сайта. Когда его спросили о том, как была выявлена эта проблема, он сказал, что тень вызывала серьёзное падение производительности и неприятные визуальные эффекты. Так, при прокрутке страницы, на которой было много видео, некоторые части страницы появлялись и исчезали. Ну что же, если тень вызывает такие проблемы — не вижу ничего плохого в том, чтобы заменить её на соответствующее изображение. Когда включена тёмная тема, к HTML-элементу добавляется класс На боковой панели есть список ссылок — вроде тех, которые ведут к профилю пользователя, к самым последним материалам, к разделу Memories. Я заметил, что здесь используется обрезка многострочного текста: Эта возможность CSS пользуется довольно хорошей браузерной поддержкой. CanIUse сообщает о том, что это свойство поддерживают (хотя и с префиксом) все ведущие браузеры. Подробности об этом свойстве можно почитать здесь. Мне нравится единообразие и простота, обеспечиваемые использованием одного и того же эффекта для множества элементов. Если это что-то и значит, то значит это то, что используемый на сайте язык дизайна единообразен, и то, что система была спроектирована аккуратно. Хорошая работа, Facebook! Во время написания этого материала свойство Более того, надо отметить, что тут имеется встроенный стиль, который меняет направление текста (возникает такое ощущение, что атрибута Если вас интересуют особенности RTL-стилизации — взгляните на этот мой материал. Вы обратили внимание на то, что для оформления фона используется градиент и цвет, похожий на цвет главной фотографии? Этот фон формируется динамически, он основан на цвете фотографии. Как это делается? Фон использует найденный ранее доминантный цвет. Я, чтобы было понятнее, выделил изображение, выводимое на странице в качестве главного фото, белой рамкой. В том случае, если в дизайне используются тёмные цвета, применяется обратный вариант градиента: Для нахождения доминантного цвета изображения можете воспользоваться этим инструментом. Мне понравился подход, используемый разработчиками Facebook при создании теней для различных элементов вроде выпадающих меню. Такая тень создаёт иллюзию объёма, гораздо более реалистичную, чем иллюзия, достижимая при использовании обычной тени. Вот CSS-код: Мне нравится это разумное решение. Вот CSS-код: Как команда Facebook справилась с этой проблемой? Очень просто: тут имеются четыре пустых элемента Уважаемые читатели! А вы находили когда-нибудь что-нибудь интересное, анализируя код сайтов, которые посещаете?
Интересно то, что на главной странице ленты аватары созданы с использованием тега и элемента
Вот стили к этому HTML-коду: .avatar-wrapper {
position: relative;
}
.avatar {
display: block;
border-radius: 50%;
}
.avatar-outline {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
border-radius: 50%;
}
Так как SVG в аватарах используется лишь в некоторых местах, могу предположить, что причина использования и
Использование в роли разделителей элементов
Я не застал тех времён, когда в качестве разделителей элементов веб-страниц использовались GIF-изображения. Но тут я увидел кое-что, напоминающее эту технику. Я так думаю, то, о чём я говорю, можно назвать div-разделителями.
Элементы margin-left: 16px
. Но в Facebook то же самое сделали, воспользовавшись элементом
Почему тут не используется внешний отступ? Как по мне, так CSS сайта (около 100 тысяч строк), который полон вспомогательных классов, способен вместить ещё один класс, позволяющий настроить отступ у нужного элемента.Использование CSS-фильтров
Иконки, созданные с помощью элементов и . А иконки мессенджера и уведомления — с использованием SVG-элементов. Причины подобного смешения технологий мне неизвестны.
.icon {
filter: invert(39%) sepia(57%) saturate(200%) saturate(200%) saturate(200%) saturate(200%) saturate(200%) saturate(147.75%) hue-rotate(202deg) brightness(97%) contrast(96%)
}
И это, кстати, продакшн-код facebook.com. Мне этот код кажется очень странным. Разве сложно заменить этот элемент на SVG-изображение и просто поменять цвет, задаваемый атрибутом
fill
?
Значок верифицированного аккаунта.icon {
filter: invert(59%) sepia(11%) saturate(200%) saturate(135%) hue-rotate(176deg) brightness(96%) contrast(94%);
}
Вот как это выглядит
Ссылки в профиле пользователяИспользование изображений для создания теней
Тень, созданная с помощью background-imagebox-shadow
. Но на самом деле это не так. Тут использован элемент x
.
Изображение, используемое для создания тениШирокое использование CSS-переменных
Мне нравится то, что дизайнеры Facebook используют CSS-переменные. Судя по тому, что я видел, к элементу :root
добавлено более 320 переменных. Эти переменные используются и в светлой, и в тёмной темах сайта.__fb-dark-mode
. Потом он переопределяет все переменные, объявленные в элементе :root
: :root {
/* Переменные светлой темы */
-fds-active-icon: #3578E5;
--fds-attachment-footer-background: #F2F3F5;
--fds-blue-05: #ECF3FF;
--fds-blue-30: #AAC9FF;
--fds-blue-40: #77A7FF;
}
.__fb-dark-mode:root, .__fb-dark-mode {
/* Переопределение переменных светлой темы */
--fds-active-icon: black;
--fds-attachment-footer-background: black;
--fds-blue-05: black;
--fds-blue-30: black;
--fds-blue-40: black;
}
Вот видео, в котором демонстрируется то, что происходит после переключения на тёмную тему. Советую смотреть его в полноэкранном режиме.Использование CSS-свойства line-clamp для обрезки многострочного текста
В подписях используется обрезка многострочного текста.element {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
Это — встроенные стили, которые, кроме того, меняются в зависимости от браузера.
Код обрезки текста в Chrome и FirefoxИспользование div для создания элементов, реагирующих на наведение на них указателя мыши
Обычно эффекты, сопровождающие наведение указателя мыши на некий элемент, создают средствами CSS. Например, если некую кнопку нужно окрасить особым оттенком серого цвета при наведении на неё указателя, достаточно сделать следующее: .element:hover {
background: #ccc;
}
Однако возникает такое ощущение, что на больших сайтах, вроде сайта Facebook, такой подход непрактичен. В процессе исследования сайта я обратил внимание на элемент, который выводится только при наведении на него указателя мыши (назовём его «hover-элемент»). В этом заключается его основная задача. Вот его стиль: .hover-div {
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
pointer-events: none;
border-radius: 6px;
inset: 4px 0px;
background-color: var(--hover-overlay);
transition-property: opacity;
transition-timing-function: var(--fds-animation-fade-out);
cursor: pointer;
}
Значение свойства opacity
этого элемента меняется средствами JavaScript с 0
на 1
. Я поэкспериментировал с ним и выяснил, что он используется для множества компонентов. Ниже приведён набор скриншотов, демонстрирующих использование этого элемента.
Использование hover-элементаИспользование свойства inset
Речь идёт о сокращённой записи значений свойства, подразумевающей воздействие на верхнюю, правую, нижнюю, и левую часть элемента. Пользоваться свойством inset
можно так: .element {
inset: 4px 0;
/* Это эквивалентно следующему: top: 4px, bottom: 4px, left: 0, right: 0 */
}
Свойство inset
настраивается для вышеописанных hover-элементов, связанных с некоторыми другими элементами. Стиль встроен в HTML. Я заметил его применение к компоненту, показанному ниже.
Синим цветом выделены области, на которые воздействует свойство insetinset
поддерживает лишь Firefox 66+.Атрибут dir=«auto» и логические CSS-свойства
На многоязычных сайтах, вроде Facebook, иногда сложно спрогнозировать то, каким именно будет контент. Например, имя пользователя в некоем компоненте имеет атрибут dir=«auto»
. Это означает, что направление текста будет зависеть от языка. Скажем, при использовании английского языка текст будет выводиться слева направо, а при использовании арабского — справа налево.dir=«auto»
недостаточно). Вот как то выглядит:
Обратите внимание на то, что к элементу добавлен стиль text-align: start
. Тут используется логическое CSS-свойство. Стиль, для LTR-макетов, будет выглядеть как text-align: right
.Динамический фон, зависящий от главной фотографии
Фон, зависящий от главной фотографии▍1. Получение доминантного цвета
Сначала нужно получить доминантный (используемый чаще других) цвет главного фото. После того, как этот цвет найден, создаётся уменьшенный вариант главной фотографии, закрашенный только этим цветом.
Нахождение доминантного цвета▍2. Добавление фона, использующего доминантный цвет
Фон, использующий найденный доминантный цвет▍3. Добавление градиента поверх фона
Для добавления градиента поверх фона используется такой CSS-код: .element {
background-image: linear-gradient(to top, #FFFFFF, rgb(255, 255, 255), rgba(255,255,255,0.7), rgba(255,255,255,0.4), rgba(255,255,255,0));
}
Добавление градиента (в дизайне используются светлые цвета).element {
background-image: linear-gradient(to top, #000, rgb(0, 0, 0), rgba(0,0,0,0.7), rgba(0,0,0,0.4), rgba(0,0,0,0));
}
Добавление градиента (в дизайне используются тёмные цвета)Множественные тени
Тени
Выпадающие меню.element {
box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1), inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}
Тут у вас может возникнуть вопрос о том, зачем тут создаётся inset-тень белого цвета с прозрачностью в 50%? Дело в том, что это — тень для тёмного режима. Ниже показан увеличенный фрагмент интерфейса, в котором используется такая тень.
Увеличенный фрагмент интерфейса с inset-теньюПустые элементы для flexbox-сеток
Я обратил внимание на то, что все сеточные макеты на сайте основаны на flexbox. Вот один из примеров такого макета, который я обнаружил в разделе фотографий пользователя.
Пустые элементы в сеточном макете.wrapper {
display: flex;
flex-wrap: wrap;
justify-items: space-between;
}
.item {
width: 205px;
}
Выглядит всё это интересно, правда? Использование значения space-between
при настройке размещения элементов — дело рискованное. Макет будет выглядеть неправильно в том случае, если, например, имеется всего три фотографии. Ниже показан пример такого макета.
Опасность использования space-between
При таком подходе подобные пустые элементы Использование вертикальных медиа-запросов
Я редко вижу вертикальные медиа-запросы, так сказать, в диком виде. Мне нравится то, что разработчики из Facebook использовали такой запрос для уменьшения ширины ленты новостей на домашней странице: @media (min-height: 700px) {
.element {
width: 584px;
}
}
Итоги
Вот и всё. Мне было очень интересно работать над этой статьёй. Исследуя дизайн сайта Facebook, я узнал много нового. Надеюсь, вы тоже нашли в моём рассказе что-то такое, что показалось вам новым и интересным.