От автора: например, вы делаете макет для поста в блог. Вы написали контент в CMS через WYSIWYG-редактор и вывели его на страницу. Потом вы открываете страницу на мобильном устройстве и видите, что параграфы растянуты на всю ширину. Слегка неудобно. Вы добавляете padding слева и справа, например, с помощью div.container.
Это будет работать ровно до тех пор, пока клиенту не захочется растянуть изображения и видео на всю ширину. Теперь ваш универсальный способ с padding не работает. У вас есть несколько вариантов:
Прописать </div><div class=»container»> в разметке в WYSIWYG. Да поможет вам Бог, если вы пойдете таким путем.
Разделить $post->content на отдельные части в CMS. Если выбрать этот способ, нужно будет написать front-end и back-end логику для рендеринга всех частей контента (части в контейнере и без). Этот способ дольше обслуживать. Вы разбили контент в базе данных только лишь для визуальной стилизации, что нельзя назвать хорошим разделением задач.
Можно обойтись без контейнера. Однако придется явно прописать padding для всех дочерних элементов кроме изображений. Если пойти этим путем, то CSS будет примерно следующим:
1 2 3 4 5 6 7 8 9 10 11 |
.post > h1, .post > h2, .post > h3, /* Repeat for every block level element in the HTML */ .post > p { margin-left: auto; margin-right: auto; max-width: 50rem; padding-left: 5%; padding-right: 5%; } |
Это сработает, но всегда будет что-то, что вы не учли. Одни изображения будут растягиваться на всю ширину, другие – нет. Все iframe’ы или только YouTube и Vimeo? Вы управляете и вхождениями и исключениями из правила. Несколько запросов с клиента, и ваш CSS код стал просто огромным.
Давайте попробуем *:not()
Я ленивый, поэтому подумал, как написать весь этот CSS код намного проще. И я нашел простое и элегантное решение с помощью селектора :not() из спецификации CSS Level 3.
1 2 3 4 5 6 7 |
.post > *:not( img ):not( video ) { margin-left: auto; margin-right: auto; max-width: 50rem; padding-left: 5%; padding-right: 5%; } |
Теперь я управляю только исключениями. Этот трюк я использую в своем блоге, чтобы вырваться из скучной, но надежной «трубы контента». Способ можно перевести на множество элементов:
1 |
.post > *:not(img):not(video):not(table):not(iframe[src*="codepen"]) { /* ... */ } |
Я просто добавляю те элементы в список, которые необходимо выдернуть из контейнера и увеличить. Способ на :not() довольно универсальный.
Цветные фоновые уровни
Эту технику можно перенести на теги section и div, чтобы задавать им разные цветные фоны (как на маркетинговых сайтах), после чего они перерабатываются таким образом, что этот div получает стили поддельного контейнера.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.post > *:not( .colored-bg ), .colored-bg > * { margin-left: auto; margin-right: auto; max-width: 50rem; padding-left: 5%; padding-right: 5%; } .colored-bg { background: lightgray; padding-top: 5%; padding-bottom: 5%; } |
Демо: макет поста в блоге
Чтобы проверить теорию, я создал стандартный макет поста в блог, в котором примерно 70 строк CSS. Мне этого вполне достаточно.
Мне нравится, к чему все идет
Буду честен, у способа есть некоторые ограничения. Выбор с помощью селектора * — довольно дорогое удовольствие, если страница огромная. Вы пишите селекторы слева направо, но CSS оценивает их справа налево. Перезаписать селектор :not() довольно сложно (см. blockquote в демо). Вычисления при изменении размеров могут также дорого обойтись браузерам.
Наверное, я буду пользоваться этим методом. Мне нравится, что я не открываю и не закрываю контейнеры. Мне нравится, что я могу писать код прямо. Мне нравится, что это относительно дешёвый и легкий способ вырваться за пределы скучной трубы контента, даже если это мало что меняет.
Сейчас я работаю над парой проектов, где блоки-обертки div реально вносят путаницу и делают код менее гибким. Мы с Chris Coyier даже обсуждали этот вопрос в последнем выпуске подкаста rapidfire на Shop Talk Show. Похоже, это отличный способ.
Источник: //daverupert.com/
Редакция: Команда webformyself.