5 приемов работы с CSS, о которых вам следует знать


    Наблюдая за потоком вопросов по CSS на Тостере уже давно заметил, что многие из них повторяются много-много раз. Да, есть совсем глупые вопросы, на которые так и тянет ответить RTFM! Но есть и более занятные. Они связаны с не совсем стандартной версткой. Не такой, чтобы глаза на лоб лезли, но и заметно выходящей за рамки условного бутстрапа и традиционных туториалов для новичков. Похожие вопросы довольно сложно загуглить — обычно вся суть в картинке, но и отвечать каждый раз надоедает. В этой статье мы постараемся посмотреть некоторые приемы, охватывающие довольно широкий круг подобных вопросов. Информация в первую очередь адресуется начинающим верстальщикам, но возможно и опытным будет, чем вдохновиться.


    1. Туда-сюда-обратно



    Начнем с простого. Если трансформировать элемент-контейнер, а затем применить противоположную трансформацию к его контенту, то можно получить много всего интересного. Это часто используют для создания косых секций. Рассмотрим следующую разметку:


    <div class='custom-section'>
        <div class='block -left'>
            <img class='background' src='...' />
            <a class='link' href=''>Summer</a>
        </div>
        <div class='block -right'>
            <img class='background' src='...' />
            <a class='link' href=''>Winter</a>
        </div>
    </div>

    Довольно просто, ничего лишнего. Из нее мы получаем вот такой результат:



    Как это произошло? Здесь мы применили transform: skew(-15deg) для блока и transform: skew(15deg) для контента — картинок и ссылок. Собственно вот и все. Применили трансформацию и отменили ее для потомков. Выглядит это примерно так:


    .custom-section {
        > .block.-left {
            transform: skew(-15deg) translate(-15%);
        }
    
        > .block.-left > .background {
            transform: skew(15deg) translateX(15%);
        }
    }

    При использовании transform: skew может возникать необходимость компенсировать длину контента или немного его подвинуть, что мы и сделали с помощью transform: translate.


    В подобных компонентах часто применяются картинки в виде тега img. Будет очень не лишним вспомнить про object-fit: cover.

    Разумеется, подобные действия можно совершить и с другими трансформациями. Например rotate дает нам возможность сделать циферблат или расположить фотографии по кругу:



    Принцип работы тот же. Применили трансформацию и отменили ее для дочерних элементов:


    .image-wrapper {
        &:nth-of-type(2) {
            transform: rotate(45deg);
            .image { transform: rotate(-45deg); }
        }
    
        &:nth-of-type(3) {
            transform: rotate(90deg);
            .image { transform: rotate(-90deg); }
        }
    
        и.т.д.
    }


    2. Бордиенты


    У нас в CSS довольно ограниченные возможности по оформлению границ элементов. Но в голове дизайнера все совсем по-другому. Это приводит к тому, что начинающий верстальщик часто встает в ступор и предлагает дать дизайнеру клавиатурой по голове. На Тостере часто спрашивают о том, как оставить от стандартного бордера только уголки, сделать двойной/тройной бордер и.т.д. Все подобные вопросы можно решить с помощью градиентов.



    Основная идея проста до невозможности: взять линейные градиенты и с помощью них нарисовать такой бордер, какой мы захотим. В нашем обществе очень сильно влияние стереотипов и многим людям видимо просто не приходит в голову, что инструменты (в частности свойства CSS) можно использовать не совсем по назначению.


    Собственно лучше всего проиллюстрирует эти слова живой пример:



    Здесь мы видим два подхода к использованию градиентов: в border-image и background-image. Первый вариант может быть удобен в сочетании со свойством border-image-slice, а второй уже давно популярен для рисования чего угодно.


    .example {
        &:nth-of-type(1) {
            border-size: 3px;
            border-style: solid;
            border-image: linear-gradient(to bottom, #86CB92 0%, transparent 40%, transparent 60%, #86CB92 100%);
            border-image-slice: 1;
        }
    
        &:nth-of-type(3) {
            background: linear-gradient(to right, #86CB92 0%, transparent 100%),
                linear-gradient(to right, transparent 0%, #86CB92 100%),
                linear-gradient(to bottom, #86CB92 0%, transparent 100%),
                linear-gradient(to bottom, transparent 0%, #86CB92 100%),
                linear-gradient(to right, #86CB92 0%, #86CB92 100%),
                linear-gradient(to right, #86CB92 0%, #86CB92 100%);
            background-size: 70% 3px, 70% 3px, 3px 70%, 3px 70%, 20% 20%, 20% 20%;
            background-position: 50% 0, 50% 100%, 0 50%, 100% 50%, 5% 5%, 95% 95%;
            background-repeat: no-repeat;
        }
    }

    В Safari как всегда есть проблемы с прозрачностями. Всегда используйте развернутую запись с border-width и border-style, как в первом примере, вместо короткой border: 3px solid transparent.

    3. Частичное дублирование стилей



    И раз уж мы говорим о бордерах, скажем пару слов о дублировании. Тоже полезный прием. Если у элемента есть бордер, мы можем взять один из его псевдоэлементов (::before или ::after), положить его сверху, задать тот же размер в 100% / 100% и полностью или частично продублировать бордер основного элемента.


    .overflow-example {
        border: solid 5px #fff;
        position: relative;
    
        &::after {
            display: block;
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            height: 100%;
            width: 100%;
            border-bottom: solid 5px #fff;
        }
    }

    Это даст возможность сделать "вылезание" контента через границу элемента:



    Подобный эффект часто встречается на рекламных страницах, так что его точно стоит взять на вооружение.


    Не забывайте добавлять pointer-events: none всем элементам, которые перекрывают контент.

    4. Контент, вырванный из контекста


    Вылезание элемента за границы родителя приводит нас к другой штуковине — вырыванию элемента из контекста. Про свойство z-index знает каждый верстальщик, но мало кто вспоминает про него, когда речь идет о многослойных бутербродах из эффектов. В результате это приводит к излишнему усложнению разметки.


    Рассмотрим пример. Нужно сделать эффект фонарика (что-то вроде освещения фона и границ элементов в некотором радиусе от курсора). Как подойти к этому вопросу?



    Допустим у нас уже есть разметка:


    <div class='custom-grid'>
        <div class='item'>
            <div class='text'>Lorem ipsum dolor sit amet</div>
        </div>
        <div class='item'>
            <div class='text'>Lorem ipsum dolor sit amet</div>
        </div>
        и.т.д.

    Можем ли мы как-то добавить подсветку прямо сюда? Да. Причем решение очень простое:


    • Кладем сверху на все это большой радиальный градиент с прозрачной дыркой в центре
    • С помощью z-index вырываем контент из текущего контекста и он автоматически располагается поверх градиента

    Сам по себе радиальный градиент не представляет из себя ничего необычного:


    .shadow {
        position: absolute;
        left: 50%;
        top: 50%;
        height: 200vh;
        width: 200vw;
        transform: translateX(-50%) translateY(-50%);
        background: radial-gradient(circle at center, transparent 0%, transparent 5%, #302015 70%, #302015 100%);
    }

    В подобных эффектах, привязанных к мышке часто применяют размеры в 200vh/200vw для того, чтобы их края не вылезали в видимую пользователем область.


    Получился бутерброд. Снизу остались бордеры, посередине лег градиент, сверху все накрылось контентом. Даже в существующую разметку такой эффект добавится всего одним элементом и парой строк CSS. Бывают конечно исключения, но все же. Осталось только оживить эффект, привязав его к мышке:


    const grid   = document.getElementById('js-grid');
    const shadow = grid.querySelector('.shadow');
    
    document.addEventListener('mousemove', (e) => {
        const rect = grid.getBoundingClientRect();
    
        window.requestAnimationFrame(() => {
            shadow.style.left = `${e.clientX - rect.left}px`;
            shadow.style.top = `${e.clientY - rect.top}px`;
        });
    });

    Подобный прием также можно применять и с модальными окнами или меню, перекрывая все остальное красивой тенью.


    5. Бутерброд из SVG и HTML


    Бутерброды. Хмм… Есть еще один. Очень полезный. Решает он следующую проблему: если у нас есть какая-то схема, карта, график или еще что-то в виде SVG картинки, вставленной в разметку, то при адаптивном изменении ее размера начинают уменьшаться или увеличиваться тексты на ней. Это мало того, что может приводить к их "размыливанию" и искажению пропорций, но и выбивает эту самую схему или график из общего стиля страницы.



    Чтобы это дело поправить, можно класть поверх SVG обычный div, в котором верстать все эти надписи абсолютным позиционированием.


    .mixed-graph {
        > .svg {
            ....
        }
    
        > .dots {
            position: absolute;
            z-index: 1;
        }
    }

    Удобно сразу делать viewbox='0 0 100 100' у картинки, чтобы координаты абсолютного позиционирования в слое HTML совпали с ними же в слое SVG.

    Таким образом мы сможем сделать условный график, на котором все надписи будут такими же, как и на всей остальной странице. В сочетании с адаптивной типографикой это может давать очень приятные в использовании результаты.





    Вместо заключения


    Начинающие верстальщики, изучайте и используйте все возможности, которые предоставляют вам ваши инструменты. Мир меняется. Многие тяжелые плагины для jQuery сейчас легко заменить парой строк CSS, да и возможности по оформлению страниц не идут ни в какое сравнение с тем, что было в начале 2000х. Пора уже изменить восприятие мира веб-разработки, принять тот факт, что "верстка" становится все более широкой областью деятельности, и начать уже делать современные сайты без оглядки на былые стереотипы и ограничения.

    Поделиться публикацией

    Похожие публикации

    Комментарии 25
      –3
      Не плохо. Добавил в закладки, где-нибудь да пригодится.
        +7

        Я понимаю, что вы привыкли. Но если вы правда писали это для новичков, то почему бы не дать примеры на CSS, а не на Sass? Вы даже не упоминаете это нигде и случайному человеку это кажется нормальным. Он копирует код, сохраняет и ничего не работает.

          –2
          Вы даже не упоминаете это нигде

          Во всех полных примерах с CodePen соответствующие вкладки недвусмысленно называются «LESS» и одним нажатием кнопки происходит переключение на скомпилированный CSS, если он нужен.
            –1
            На заборе тоже много чего написано. В статье у вас это нигде не упоминается, хотя все на sass написано. Сделайте хоть дисклеймер какой!
              +2

              Он нужен, потому что в заголовке статьи написано «CSS», а не «SASS».

                +2
                По минусам понимаю, что попал в новую аудиторию. На тостере «начинающие», которые задают такие вопросы, уже знают о препроцессорах и используют их. Тот факт, что кто-то использовал вложенность (только ее) в ответе, никого не смущает. Более ценен факт передачи идеи. По всей видимости у аудитории на хабре немного другие взгляды на этот вопрос с синтаксисом. Принял к сведению.
                  0
                  У аудитории на Хабре больше любви к последовательности. Сказал CSS — пиши примеры на CSS. Сказал CSS, а пишешь на Sass — хотябы предупреди об этом. Кто-то может быть знаком с препроцессорами, кто-то нет, а статья пишется для максимально широкой аудитории.
                    0

                    Ппц вы зануды, человек старался, писал статью, а вы минусов накидали за препроцессора, которые используют везде

                      0

                      Препроцессоры*

                        +1

                        Занудство часто спасает от печальных последствий. И все же не все используют препроцессоры. Наоборот сейчас мода на них идёт на убыль с приходом кастомных свойств и предложением введения вложенности в самом CSS.

                          +2

                          Кастомные свойства в css используются с помощью postcss, т.к. поддержка плачебна, знать о postcss и не знать о препроцессорах, серьезно?

                            +1
                            Поддержка 86% (эдж с 16 версии, фф с 38, хром с 49, сафари с 9.1). Если вам не нужно поддерживать легаси в виде ие11 и андроида 4.4, можно вполне обойтись без постцсс. Опять же мы говорим про то, что нужно называть вещи своими именами, а не про то, что знает или не знает читатель.
                      +1
                      На Тостере люди читают ответы на интересующие их профессиональные вопросы.
                      На Хабре же, C# девелопер может прочитать вашу статью, чисто из интереса «Что-там новенького и интересного в веб-разработку завезли?». Как я и сделал.
                      А что есть этот «SASS» и препоцессоры от меня так же далеко, как для вас WPF-контролы. Но узнаю о том, что это не CSS, и что это вообще такое, я, почему-то, из комментариев.

                      Не надо так.
                  0
                  Спасибо!
                    +2

                    Спасибо за интересные штуки. Однако проблема подобных статей в том, что они не нужны. То есть я сейчас на нее наткнулся, прочел и забыл. А когда будет такая задача хз, как гуглить. И так всегда.

                      0
                      Добавьте в закладки и проставьте кастомные теги. Я таким образом хабр в небольшой и неплохой справочник превратил.
                        +1

                        Спасибо, у меня полный Pocket всякой годноты. Но не помогает. Вот получил Sketch template со всякими извращениями, а как его мапить с тэгами?

                        +2
                        Не проблема. Статья нужна для того чтобы показать что это можно делать при помощи простых средств. Она не предназначена для зазубривания))
                          +1
                          Примеры приведены в CodePen. Ставите сердечко там и сможете найти их в своей коллекции, когда понадобится.
                            +1

                            Тут важна идея. Не стоит просто копировать код в свой проект. Вот например, первый пример с обратным поворотом дочернего элемента, вроде элементарно, но многие не догадываются. А когда прочитаешь, в голове остается, что так делать можно.
                            Когда читаешь много таких штук, многое остается в голове, и при случае будет использовано.

                            +1
                            блин сложно спроектировать и изначально заложить такое, а так дельное описание, спасибо
                              +2
                              такие статьи всегда полезны куче народа, и не только начинающим.

                              я только одного не понял: зачем во все примеры пихать исходники фона (svg) и какой-то левый шрифт? это только усложняет разбор стилей.
                                +1
                                да, было бы удобнее если бы декор располагался внизу css (все-таки пример, а не реальный проект)
                                +1
                                Очень порадовал 4й пример. При решении такой задачи прибегнул бы к canvas со всеми вытекающими, на css с минимальным js в голову бы не пришло.
                                  0
                                  Сам девелопер я не первый год, но до такого дойти ещё не смог. Вот и вопрос — кто есть про по css и сколько требуется времени чтобы им стать? А так спасибо за материал!

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое