Я хочу, чтобы на следующие минут 30 или около того, вы забыли про CSS. Забыли о веб-разработке. Забыли о цифровых пользовательских интерфейсах.
И когда вы это сделаете, я хочу, чтобы ваш разум начал странствие. Странствие по времени. В то время, когда вы были совсем юны. В ваш первый день в школе.
В то время все было проще. Тогда вам надо было беспокоиться лишь о рисовании фигур и быть начеку с недержанием.
Посмотрите на точки сверху. Обратите внимание, как некоторые из них собраны рядом, а некоторые разделены. Я хочу чтобы вы объединили их в пять групп, как вам кажется нужным.
Вперед. Проверьте, что никто вас не видит, и затем нарисуйте окружности вокруг каждой из пяти групп вашим детским пальцем.
У вас скорее всего получилось что-то вроде этого, так? (И как бы то ни было, не говорите что просто прокрутили страницу не выполняя задание. Иначе будет фейспалм.)
На самом деле, эти две точки справа могут быть объединены и по-другому. Если вы поместили их в одну группу, думаю это нормально.
Прежде чем я продолжу, скажите, у вас получилось что-то вроде этого?
Полагаю, что нет. Правильно?
Но это именно то, что вы будете делать, если поставите свои брейкпоинты на позициях, точно совпадающих с ширинами популярных устройств (320px, 768px, 1024px).
Вам когда-нибудь доводилось слышать или говорите что-то такое:
Брейкпоинт medium идет до 768px или включает 768? А, вижу… А это iPad в горизонтальной ориентации, или это large? А, нет, large идет от 768px и выше. Понял. А small получается 320px? Что это за интервал от 0 до 319? Брейкпоинт для муравьев?
Я могу продолжить показывать, как правильно расставлять брейкпоинты, и все на этом. Но я нахожу очень странным, что приведенный выше метод (“глупого группирования”) настолько распространен.
В чем может быть причина этого?
Думаю причина этой проблемы, как и многих других проблем, состоит в неправильной терминологии. Кажется мы смешиваем понятия “границы” и “интервалы” в наших обсуждениях и реализациях брейкпоинтов.
Скажите, если вы делаете брейкпоинты на Sass, вы создаете переменную $large, которая, к примеру, равна 768px?
Это нижняя граница интервала, который вы называете large, или верхняя? Если это нижняя, то вам не нужна переменная $small, потому что она будет равна 0, так ведь?
А если это верхняя граница, как вы собираетесь называть брейкпоинты, которые выше, large-and-up? Это должен быть media-запрос с минимальной шириной medium, правильно?
И если вы подразумеваете только границу, когда говорите large, то это приведет к неразберихе в дальнейшем, потому что media-запрос — это всегда интервал.
Эта ситуация запутана и мы тратим время, думая об этом. Поэтому у меня есть три предложения:
- Расставляйте брейкпонты правильно
- Именуйте интервалы разумно
- Будьте повествовательны
Совет #1: Расставляйте брейкпоинты правильно
Что знаичит правильный брейкпоинт?
Школьник в вашем обличии уже нарисовал окружности. Я просто перевел их в прямоугольники для вас.
600px, 900px, 1200px и 1800px если вы планируете показать что-то особенное людям с гигантскими мониторами.
Эти точки, с которыми игрался школьник в вашем обличии, на самом деле были визуализацией 14 самых популярных размеров экранов:
И теперь мы можем создать очень простую картинку, которая позволит разговаривать на одном языке дизайнерам, разработчикам, тестировщикам и людям, одетым в деловые пиджаки.
Совет #2: Именуйте интервалы разумно
Честно говоря, вы можете назвать ваши брейкпоинты папа-медведь и малыш-медведь, если вам хочется. Но если я собираюсь сесть с дизайнером и обсудить, как сайт должен выглядеть на разных устройствах, я хочу, чтобы это прошло как можно быстрее. Если то, что вы назовете размер “планшет в портретной ориентации”, ускорит дело, то я за. Да блин, я даже готов простить вам если вы назовете его “iPad в портретной оринтации”.
“Но размеры меняются!” — можете возразить вы. “Телефоны становятся больше, планшеты становятся меньше!”
Однако срок годности CSS вашего сайта равен примерно 3 годам (конечно, если это не Gmail). В течение двух таких временных промежутков iPad был с нами и до сих пор не свергнут.
Так что 1024×768 остается надолго, друзья. Давайте не прятать головы в песок.
Вывод: общение очень важно. Не ограничивайте себя от полезной терминологии.
Совет #3: Будьте повествовательны
Знаю, знаю, снова это слово “повествовательность”. Другими словами, ваш CSS должен определять что должно произойти, а не как это должно произойти. “Как” можно спрятать в каком-нибудь миксине.
Как говорилось ранее, часть недоразумений насчет брейкпоинтов вызвана тем, что переменные определяющие границу интервала используются как имя этого интервала. $large: 600px
ровным счетом не говорит ни о чем, так как large — это интервал. Это то же самое что написать var coordinates = 4;
.
Поэтому, мы можем спрятать эти детали в миксине, вместо того чтобы допускать их использование в коде. Или мы можем поступить еще лучше: не использовать переменные вообще.
Сначал я написал приведенный ниже код как упрощенный пример. Но я думаю он покрывает все основные задачи. Чтобы заценить его в действии, посмотрите этот pen. Я использую Sass, потому что не могу представить разработку сайта без него. Эта логика применима и по отношению к CSS и Less.
@mixin for-phone-only {
@media (max-width: 599px) { @content; }
}
@mixin for-tablet-portrait-up {
@media (min-width: 600px) { @content; }
}
@mixin for-tablet-landscape-up {
@media (min-width: 900px) { @content; }
}
@mixin for-desktop-up {
@media (min-width: 1200px) { @content; }
}
@mixin for-big-desktop-up {
@media (min-width: 1800px) { @content; }
}
// использование
.my-box {
padding: 10px;
@include for-desktop-up {
padding: 20px;
}
}
Настоятельно рекомендую разработчикам указывать суффикс -up
или -only
.
Неоднозначность порождает путаницу.
Очевидным недостатком может быть то, что приведенный пример не поддерживает кастомные media-запросы. Однако, есть хорошие новости. Если вам нужен кастомный media-запрос, напишите кастомный media-запрос. (На практике, если мне нужна большая опциональность, чем приведено выше, то я бегу в объятия к своему любимому инструментарию Sussy)
Другим недостатком может быть то, что у меня получилось несколько миксинов. По правде говоря, один миксин будет делать то же самое, если передавать в него потом необходимый размер:
@mixin for-size($size) {
@if $size == phone-only {
@media (max-width: 599px) { @content; }
} @else if $size == tablet-portrait-up {
@media (min-width: 600px) { @content; }
} @else if $size == tablet-landscape-up {
@media (min-width: 900px) { @content; }
} @else if $size == desktop-up {
@media (min-width: 1200px) { @content; }
} @else if $size == big-desktop-up {
@media (min-width: 1800px) { @content; }
}
}
// использование
.my-box {
padding: 10px;
@include for-size(desktop-up) {
padding: 20px;
}
}
Да, это работает. Но вы не получите ошибок компиляции, если передадите неподдерживаемый размер. Не говоря уже о том, что синтаксис @include for-desktop-up {...}
выглядит приятнее, чем @include for-size(desktop-up) {...}
.
Недостатоком обоих приведенных примеров может быть то, что я печатаю 600px дважды, и так же 599px. Конечно, мне следовало просто использовать переменные и вычитать еденицу там, где это нужно.
Если вы хотите сделать это, вперед, но я, конечно, делать этого не буду. На это есть пара причин:
- Это не те вещи, которые меняются часто. И это не числа, которые будут использоваться где-то еще в коде. Нет никаких проблем, что это не переменные, если конечно вы не собираетесь использовать брейкпоинты Sass в скрипте JS.
- Код становится противным, когда вы переводите числа в строки в Sass. Ниже приведен пример цены, которую приходится заплатить за вашу веру в то, что повторение переменной дважды — это самое худшее из зол:
@mixin for-size($size) {
@if $size == phone-only {
@media (max-width: 599px) { @content; }
} @else if $size == tablet-portrait-up {
@media (min-width: 600px) { @content; }
} @else if $size == tablet-landscape-up {
@media (min-width: 900px) { @content; }
} @else if $size == desktop-up {
@media (min-width: 1200px) { @content; }
} @else if $size == big-desktop-up {
@media (min-width: 1800px) { @content; }
}
}
// использование
.my-box {
padding: 10px;
@include for-size(desktop-up) {
padding: 20px;
}
}
О, и раз я уже перешел на повышенный тон в предыдущих параграфах… Мне жаль того дурака, который делает что-то прекрасное, как хранение брейкпоинтов в списке Sass, и делает цикл, который их обходит, чтобы вывести media-запросы, или что-то такое же нелепое, что заставляет последующих разработчиков ломать голову пытаясь это расшифровать.
Сложность — это место, где прячутся баги.
Подходя к концу, отметим, что вы можете думать “разве я не должен основывать брейкпоинты на контенте, а не на устройствах?”. Что ж, я поражен, что вы зашли так далеко, и ответ — “да”… для сайтов с одним макетом. Или если у вас есть много макетов и вам нравится создавать отдельный набор брейкпоинтов для каждого макета. О, и еще, если дизайн сайта не меняется часто или вам нравится менять брейкпоинты каждый раз, когда он меняется. Вы же хотите держать брейкпоинты основанными на контенте, так же?
Для сложных сайтов, жизнь будет куда проще, если вы выберите группу брейкпоинтов, которые подходят для всего сайта целиком.
На этом все! Но эта статья получилась не настолько няшной, как я хотел, так что дайте-ка подумать как мне исправиться…
О, знаю!
Бонусные советы по созданию брейкпоинтов
- Если вам нужно исследовать CSS брейкпоинты для размеров экранов больше, чем ваш монитор, используйте режим “responsive” в панели разработчика Chrome и вводите любой гигантский размер, какой хотите.
- Синяя полоска сверху показывает запросы с
max-width
, а оранжевая — сmin-width
, зеленая показывает запросы, содержащие и то и другое. - Кликнув на media-запрос можно установить соответствующую ширину экрана. Если кликать на зеленый media-запрос больше одного раза, то он переключается между минимальной и максимальной ширинами.
- Правый клик по media-запросу переводит к определению этого правила в CSS.
Благодарю вас за чтение. Комментируйте, делитесь своими идеями. Я буду рад их услышать. И кликните на кнопку “поделиться”, если считаете, что я заслужил это, либо просто забейте на нее, если не боитесь, что я буду рыдать по ночам 🙂
Статью перевел aziev. Оригинал на Medium.freecodecamp.com доступен по ссылке.