Вопросы про SVG порадовали. Неужели люди настолько часто добавляют\удаляют иконки в проекте что для этого нужен вебпак? Какой-то вебпак головного мозга получается. Можно же просто руками собрать спрайт, вместо раскидывания всех иконок по проекту. Можно сделать несколько таких спрайтов для разных частей приложения. Проблема высосана из пальца на самом деле и получается что инструмент диктует решение, а не здравый смысл.
А теперь к позитивному: сталкивались ли с FOUC при асинхронных стилях и как лечили?
Это правда. Можно в data записать, но тогда придётся жить с предупреждениями в консоли, что не очень приятно. Если компонент не один действительно проще рекурсивный фриз сделать. (компоненты с огромными списками обычно одни на всю страницу)
Странный обзор. А как же плюсы и минусы конкретных решений? Для новичка это самое важное: понять какую задачу решает инструмент и его ограничения. Вы перечислили очень много спорных инструментов и решений, которые подойдут явно не всем. Мне кажется, если какой-нибудь сферический джуниор в вакууме (в плане CSS) потащит это всё в проект (при условии что у него есть такая возможность конечно) через какое-то время он столкнётся с тем что это будет просто невозможно поддерживать, а переписывать уже поздно.
Больше не нужна поддержка IE8? Просто удалите Autoprefixer!
Autoprefixer не про IE, а про кроссбраузерность. Если нужна поддержка IE, то одного автопрефиксера может быть недостаточно. И наоборот, если поддержка IE не нужна это совсем не означает что от него надо отказаться.
CSS-in-JS снимает с разработчиков задачу именования и группировки блоков, безо всяких сложных конвенций.
И лишает нас возможности удобной отладки CSS (например забываем про быстрый поиск CSS по селектору). У каждого подхода есть свои особенности. В моём подходе есть чёткий набор правил и ограничений, который если соблюдать то не возникнет вопроса «а как мне сделать это?». Вы правильно заметили что БЭМ можно трактовать по-разному из-за довольно широких определений. С наличием документированных правил я не вижу никаких проблем в освоении такого подхода, он как раз направлен на то чтобы максимально уменьшить возможность неоднозначной трактовки БЭМ.
Зато если вам нужно будет поменять цвет нескольких типов блоков внутри списка, вам придется обойти их все, и поменять их соответствующие варианты.
Как и в любом другом решении. Если ссылки в одном списке отличаются от ссылок в другом это нужно явно указывать в модификаторе. Разница лишь в том что в классическом случае вы меняете свойство (во всех компонентах), а в моём модификатор, при этом лишаетесь минусов классического подхода со специфичностью.
Да, это одна из особенностей этого подхода когда дело касается one-for-all компонентов типа ссылок, кнопок. Так как таких компонентов на всю систему обычно не больше десятка особого дискомфорта это не доставляет. Но даже если же таких компонентов сотни и тысячи я бы всё-равно предпочёл писать именно так, а не опираться на специфичность селектора. Гораздо проще держать в голове контексты одного компонента, чем контексты тысяч компонентов куда он подключается. Плюс в моём подходе я вижу все контексты явно, а в случае если они не в компоненте то я понятия не имею что будет дальше с ним происходить. Отсюда вытекает неизбежный ад с выстраиванием цепочки подключения файлов и повышением специфичности. Чтобы это полностью исключить я и пришёл к такой системе.
Но если вы хотите обсудить как следить за тем чтобы оно всё не перемешалось то здесь множество работающих вариантов, люди ведь как-то выучили БЭМ и не забывают как он работает.
Есть код ревью, есть внутренняя документация, есть обучение внутри команды, можно банально не допускать людей до вёрстки пока они не освоили подходы внутри проекта.
Оно не сразу даётся в первое время, особенно когда хочется всё сделать на каскаде. Но как только привыкаешь к этим паттернам больше вообще не задумываешься где какие свойства прописать.
Я не совсем понял о каких сложностях контроля можно говорить в этом случае. Если где-то опечатка то она сразу проявится в интерфейсе, вы ведь проверяете финальный результат правок в вёрстке? Зависимостей по селекторам и порядку подключения файлов нет, поэтому и тестировать это не нужно совсем.
Каждый компонент получается полностью изолированным от другого. Так что если вы решите поменять цвет ссылок внутри любого списка вам не нужно будет идти в каждый компонент, который реализует какой-то список. Достаточно лишь поменять значение у модификатора ссылки. Список не знает как устроены ссылки, а ссылкам не важно куда они вложены и наоборот. Для меня это самая удобная система на данный момент, потому что сильной связанности между компонентами нет. Исключение это публичный интерфейс компонента, как выше в примере с block-font-size. Такие вещи должны быть унифицированы и использоваться по минимуму. Такой же интерфейс можно использовать для изменения стиля через :hover и другие состояния в случаях когда у элемента уже преднастроено свойство, которое нужно изменить. Например для заливки SVG иконок по наведению на родителя.
Здесь смешались ответственности селекторов. Menu item получается отвечает и за раскладку (иначе зачем вообще этот класс) и за презентацию.
Если вы используете компонент внутри компонента, то нужно использовать модификатор там где задано конкретное свойство. Вам ведь нужно стилизовать ссылку в первую очередь?
Таким образом получим такую разметку:
Это может показаться многословным поначалу, но благодаря такой системе у нас никогда не возникнет конфликтов, если мы не будем пытаться перезаписать уже существующие свойства с помощью миксинов. Миксины очень мощная и нужна вещь, но это именно тот случай когда они только усложняют и разработку и поддержку.
Медиавыражения, например, я реализовал с помощью миксинов, где я могу просто повесить класс на элемент и он будет отображаться в зависимости от запроса.
Так как display: none никогда не нужно перезаписывать здесь вполне допустимо использование !important.
Но как быть если хочется вынести раскладку или презентацию в отдельный класс?
Очень просто: миксовать классы только с разной ответственностью. Если нужно добавить единое скругление углов к компоненту, то этот компонент не должен отвечать за свойство border-radius. Тоже самое с отступами, фоном, позиционированием и так далее. Компонент должен быть либо максимально открыт к изменениям, либо реализовывать всё тоже самое через модификаторы.
Как понять что можно добавить на компонент, а что нет?
Очень просто: сначала добавить его в разметку и посмотреть какие свойства он определяет. Ни одно из этих свойств родительский компонент переопределять не должен, а вместо этого нужно реализовать отдельный модификатор для дочернего компонента.
Иногда это может быть не очень удобно, особенно когда у всех компонентов одинаковые размеры шрифта в сборе, но разные по отдельности.
В таком случае я предоставляю открытый интерфейс таким компонентам. Например:
Не смешивать классы для презентации и для раскладки? Если вам нужно изменить отображение компонента через другой класс то нужно использовать модификатор, всё очень просто. Но чтобы это не было в пустоту думаю будет проще если вы приведёте конкретный пример.
У меня эта проблема решена на архитектурном уровне с помощью БЭМ и переменных. Порядок подключения файлов не имеет никакого значения и я действительно не знаю в каком порядке вебпак мне это собирает, потому что я отвязан от этой зависимости. Я управляю порядком только на верхнем уровне архитектуры: глобальные стили, стили компонентов и стили страницы. Более того, специфичность селекторов тоже не имеет никакого значения, всё работает через переменные. Без переменных решить эту проблему невозможно, поэтому если нужна first class поддержка IE нужно искать другие решения типа того же CSS in JS.
Думаю, что нужно спросить у Фейсбука почему так, если у них с самого начала была какая-то методология и они её придерживались. Методология всё же не исключает ошибок разработчика или незнания инструмента. Сделаю глупое предположение что там новый код вперемешку с легаси и нет код ревью для CSS.
БЭМ, CSS переменные и грамотная архитектура решают все проблемы с конфликтами свойств и позволяют вообще отказаться от зависимости на порядок следования правил вне компонентов. Более того, они полностью решают проблему увеличения специфичности селекторов и про всякие !important можно забыть. Другое дело что не каждый хочет в это глубоко погружаться, особенно если человек пришёл во фронтенд не из вёрстки. Вот даже интересно есть ли у фейсбука вопросы по вёрстке в интервью, как например у Яндекса.
Наличие !important при двух классах на элементе это не проблема CSS, а проблема отсутствия методологии, грамотной архитектуры и разграничения обязанностей у селекторов. Единственное исключение это display none, который всегда должен перезаписывать свойства компонента. Если каскад был основной причиной выбора CSS in JS то это как минимум странно.
Несомненно, CSS in JS имеет своё применение и сильные стороны. Можно ли на нём сделать небольшое приложение? Запросто. Хотел бы я его использовать на большом проекте? Да ни в раз.
То что вы описали это ошибка Vue. Гидратация должна всегда быть failsafe. Safai конечно тоже молодец что без спроса меняет DOM, но такие вещи не должны ломать всё приложение.
Совсем недавно узнал что любой отзыв из Яндекс.Маркета могут удалить просто так. Приходит «письмо счастья» что отзыв был удалён автоматической системой фильтрации, вот содержание:
Ваш отзыв отклонён системой автоматической фильтрации, которая борется с накрутками и спамом. Принципы работы системы не разглашаются, просим Вас отнестись с пониманием.
Дело в том, что обжаловать это как-либо невозможно (да и нафиг нужно). При чём система удаляет даже отзывы в которых ответил сам продавец (sic!), с наличием номера заказа. И распространяется это только на отзывы к магазинам, на отзывах к товарам такого нет (получается что накрутка рейтинга у товара не так страшна как накрученный рейтинг у магазина). Ни один отзыв на товар у меня не удалили с 2010 года, а абсолютно все отзывы на продавцов эта замечательная система посчитала за спам, хотя были как положительные, так и отрацательные отзывы.
После таких приключений никакого доверия к системе отзывов в Яндекс.Маркете у меня больше нет.
А теперь к позитивному: сталкивались ли с FOUC при асинхронных стилях и как лечили?
В вебе можно и это в том числе.
Там используется RxJS.
Спасибо за статью!
Подождите, так не все так говорят? Кажется, у меня Нижегородец головного мозга.
P. S. Круто видеть что фото Андрея Орехова теперь и на Хабре.
Или чтобы этого не делать достать данные из замыкания. Думаю понятно что флаг
dataLoaded
нужен только из-за отсутствия реактивности уitem
.Статья крутая, спасибо!
Странный обзор. А как же плюсы и минусы конкретных решений? Для новичка это самое важное: понять какую задачу решает инструмент и его ограничения. Вы перечислили очень много спорных инструментов и решений, которые подойдут явно не всем. Мне кажется, если какой-нибудь сферический джуниор в вакууме (в плане CSS) потащит это всё в проект (при условии что у него есть такая возможность конечно) через какое-то время он столкнётся с тем что это будет просто невозможно поддерживать, а переписывать уже поздно.
Autoprefixer не про IE, а про кроссбраузерность. Если нужна поддержка IE, то одного автопрефиксера может быть недостаточно. И наоборот, если поддержка IE не нужна это совсем не означает что от него надо отказаться.
И лишает нас возможности удобной отладки CSS (например забываем про быстрый поиск CSS по селектору). У каждого подхода есть свои особенности. В моём подходе есть чёткий набор правил и ограничений, который если соблюдать то не возникнет вопроса «а как мне сделать это?». Вы правильно заметили что БЭМ можно трактовать по-разному из-за довольно широких определений. С наличием документированных правил я не вижу никаких проблем в освоении такого подхода, он как раз направлен на то чтобы максимально уменьшить возможность неоднозначной трактовки БЭМ.
Как и в любом другом решении. Если ссылки в одном списке отличаются от ссылок в другом это нужно явно указывать в модификаторе. Разница лишь в том что в классическом случае вы меняете свойство (во всех компонентах), а в моём модификатор, при этом лишаетесь минусов классического подхода со специфичностью.
Но если вы хотите обсудить как следить за тем чтобы оно всё не перемешалось то здесь множество работающих вариантов, люди ведь как-то выучили БЭМ и не забывают как он работает.
Есть код ревью, есть внутренняя документация, есть обучение внутри команды, можно банально не допускать людей до вёрстки пока они не освоили подходы внутри проекта.
Оно не сразу даётся в первое время, особенно когда хочется всё сделать на каскаде. Но как только привыкаешь к этим паттернам больше вообще не задумываешься где какие свойства прописать.
Я не совсем понял о каких сложностях контроля можно говорить в этом случае. Если где-то опечатка то она сразу проявится в интерфейсе, вы ведь проверяете финальный результат правок в вёрстке? Зависимостей по селекторам и порядку подключения файлов нет, поэтому и тестировать это не нужно совсем.
Каждый компонент получается полностью изолированным от другого. Так что если вы решите поменять цвет ссылок внутри любого списка вам не нужно будет идти в каждый компонент, который реализует какой-то список. Достаточно лишь поменять значение у модификатора ссылки. Список не знает как устроены ссылки, а ссылкам не важно куда они вложены и наоборот. Для меня это самая удобная система на данный момент, потому что сильной связанности между компонентами нет. Исключение это публичный интерфейс компонента, как выше в примере с block-font-size. Такие вещи должны быть унифицированы и использоваться по минимуму. Такой же интерфейс можно использовать для изменения стиля через :hover и другие состояния в случаях когда у элемента уже преднастроено свойство, которое нужно изменить. Например для заливки SVG иконок по наведению на родителя.
Здесь смешались ответственности селекторов. Menu item получается отвечает и за раскладку (иначе зачем вообще этот класс) и за презентацию.
Если вы используете компонент внутри компонента, то нужно использовать модификатор там где задано конкретное свойство. Вам ведь нужно стилизовать ссылку в первую очередь?
Таким образом получим такую разметку:
Это может показаться многословным поначалу, но благодаря такой системе у нас никогда не возникнет конфликтов, если мы не будем пытаться перезаписать уже существующие свойства с помощью миксинов. Миксины очень мощная и нужна вещь, но это именно тот случай когда они только усложняют и разработку и поддержку.
Медиавыражения, например, я реализовал с помощью миксинов, где я могу просто повесить класс на элемент и он будет отображаться в зависимости от запроса.
Так как
display: none
никогда не нужно перезаписывать здесь вполне допустимо использование !important.Но как быть если хочется вынести раскладку или презентацию в отдельный класс?
Очень просто: миксовать классы только с разной ответственностью. Если нужно добавить единое скругление углов к компоненту, то этот компонент не должен отвечать за свойство border-radius. Тоже самое с отступами, фоном, позиционированием и так далее. Компонент должен быть либо максимально открыт к изменениям, либо реализовывать всё тоже самое через модификаторы.
Как понять что можно добавить на компонент, а что нет?
Очень просто: сначала добавить его в разметку и посмотреть какие свойства он определяет. Ни одно из этих свойств родительский компонент переопределять не должен, а вместо этого нужно реализовать отдельный модификатор для дочернего компонента.
Иногда это может быть не очень удобно, особенно когда у всех компонентов одинаковые размеры шрифта в сборе, но разные по отдельности.
В таком случае я предоставляю открытый интерфейс таким компонентам. Например:
Не смешивать классы для презентации и для раскладки? Если вам нужно изменить отображение компонента через другой класс то нужно использовать модификатор, всё очень просто. Но чтобы это не было в пустоту думаю будет проще если вы приведёте конкретный пример.
У меня эта проблема решена на архитектурном уровне с помощью БЭМ и переменных. Порядок подключения файлов не имеет никакого значения и я действительно не знаю в каком порядке вебпак мне это собирает, потому что я отвязан от этой зависимости. Я управляю порядком только на верхнем уровне архитектуры: глобальные стили, стили компонентов и стили страницы. Более того, специфичность селекторов тоже не имеет никакого значения, всё работает через переменные. Без переменных решить эту проблему невозможно, поэтому если нужна first class поддержка IE нужно искать другие решения типа того же CSS in JS.
БЭМ, CSS переменные и грамотная архитектура решают все проблемы с конфликтами свойств и позволяют вообще отказаться от зависимости на порядок следования правил вне компонентов. Более того, они полностью решают проблему увеличения специфичности селекторов и про всякие !important можно забыть. Другое дело что не каждый хочет в это глубоко погружаться, особенно если человек пришёл во фронтенд не из вёрстки. Вот даже интересно есть ли у фейсбука вопросы по вёрстке в интервью, как например у Яндекса.
Наличие !important при двух классах на элементе это не проблема CSS, а проблема отсутствия методологии, грамотной архитектуры и разграничения обязанностей у селекторов. Единственное исключение это display none, который всегда должен перезаписывать свойства компонента. Если каскад был основной причиной выбора CSS in JS то это как минимум странно.
Несомненно, CSS in JS имеет своё применение и сильные стороны. Можно ли на нём сделать небольшое приложение? Запросто. Хотел бы я его использовать на большом проекте? Да ни в раз.
Дело в том, что обжаловать это как-либо невозможно (да и нафиг нужно). При чём система удаляет даже отзывы в которых ответил сам продавец (sic!), с наличием номера заказа. И распространяется это только на отзывы к магазинам, на отзывах к товарам такого нет (получается что накрутка рейтинга у товара не так страшна как накрученный рейтинг у магазина). Ни один отзыв на товар у меня не удалили с 2010 года, а абсолютно все отзывы на продавцов эта замечательная система посчитала за спам, хотя были как положительные, так и отрацательные отзывы.
После таких приключений никакого доверия к системе отзывов в Яндекс.Маркете у меня больше нет.