Руководство по CSS-маскам: решения распространенных проблем дизайна

Руководство по CSS-маскам: решения распространенных проблем дизайна

27 февраля 2024 г.

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

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

Если это вас не взбодрило, то, думаю, я не знаю, что поможет! Хорошо, поехали.

https://youtu.be/xz9jkLceRGQ?embedable=true

CSS mask-image Объяснение

Итак, прежде чем забегать вперед, нам нужно понять, что мы делаем и как это на самом деле работает. Мы собираемся использовать свойство CSS mask-image. Правила и синтаксис mask-image, вероятно, покажутся вам немного знакомыми. Они очень похожи на свойства CSS background-image.

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

CSS mask-image example with fully opaque and fully transparent areas

А частично непрозрачные области позволят частично увидеть то, что находится за ними.

CSS mask-image example with partially opaque and partially transparent areas

Хорошо, а как насчет примера?

Использование CSS mask-image с linear-gradients для создания эффекта затухания для прокручиваемого контейнера

Наша цель — создать эффект затухания вверху и внизу нашего контейнера с прокруткой, как мы видим здесь.

CSS mask-image example fadeout at top and bottom of a scrolling container

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

CSS mask-image example fadeout at top and bottom of a scrolling container

Итак, если мы подумаем о том, что нам нужно, мы хотим поместить маску поверх нашего контейнера прокрутки, и она будет исчезать сверху и снизу. Для этого нам понадобится использовать два linear-gradient с нашим свойством mask-image. Один градиент будет плавно переходить от полностью непрозрачного черного цвета сверху вниз к низу, где он должен будет стать прозрачным. И наоборот, вверху он потускнеет от полностью непрозрачного внизу до прозрачного вверху.

Итак, начнем сначала с низа. Для этого мы добавим свойство mask-image. И нам нужно добавить линейный градиент. Поскольку сначала мы делаем низ, мы заставим этот градиент идти «вниз». Кроме того, нам нужно, чтобы фейды имели высоту 5 см, поэтому мы добавим для этого специальное свойство, чтобы его можно было использовать несколько раз.

:root {
    --fadeHeight: 5em;
}

.container {
    mask-image: linear-gradient(to bottom)
}

Итак, для начала мы начнем с полностью непрозрачного черного цвета, а затем он будет полностью непрозрачным черным по высоте всего контейнера, пока мы не доберемся до того места, где мы хотим, чтобы началось затухание. Для этого мы воспользуемся расчетом, а затем, наконец, сделаем его прозрачным внизу.

.container {
    mask-image:
        linear-gradient(
            to bottom,
            black,
            black calc(100% - var(--fadeHeight)),
            transparent
        )
}

Теперь мы видим, что эффект затухания находится внизу.

CSS mask-image example fadeout at the bottom of a scrolling container

Теперь нам нужно добавить верх, поэтому мы добавим еще один linear-gradient. На этот раз мы собираемся начать снизу и идти вверх, поэтому добавим «сверху», и вначале он будет полностью непрозрачным черным.

Этот градиент будет противоположным нижнему затуханию. Это будет 100 процентов высоты минус высота затухания, поэтому мы снова воспользуемся расчетом.

.container {
    mask-image:
        linear-gradient(
            to top,
            black,
            black calc(100% - var(--fadeHeight)),
            transparent
        ),
        linear-gradient(
            to bottom,
            black,
            black calc(100% - var(--fadeHeight)),
            transparent
        )
}

Но на данный момент мы фактически сломали нашу маску. Внизу он больше не исчезает, как мы ожидали.

CSS mask-image example fadeout at top and bottom of a scrolling container broken because masks are improperly overlapping

Почему это происходит?

Что ж, если подумать, мы просто применили две маски, которые точно перекрывали друг друга. А это означает, что теперь ко всему контейнеру применена полностью непрозрачная черная маска. Что нам действительно нужно сделать, так это в обоих этих linear-gradients освободить место для плавных переходов сверху и снизу.

Итак, на нашей нижней маске нам нужно сделать ее прозрачной, прежде чем она станет черной, чтобы освободить место для затухания вверху. Он должен оставаться прозрачным с высотой затухания, чтобы мы могли использовать наше пользовательское свойство --fadeHeight. Нам также нужно сделать то же самое с затуханием сверху, linear-gradient, чтобы освободить место для затухания внизу.

.container {
    mask-image:
        linear-gradient(
            to top,
            transparent,
            transparent var(--fadeHeight),
            black,
            black calc(100% - var(--fadeHeight)),
            transparent
        ),
        linear-gradient(
            to bottom,
            transparent,
            transparent var(--fadeHeight),
            black,
            black calc(100% - var(--fadeHeight)),
            transparent
        )
}

Хорошо, и как мы справились?

CSS mask-image example fadeout at top and bottom of a scrolling container with two linear-gradients

Отлично, теперь исчезает в обоих направлениях.

И последнее, что следует отметить: в этом примере Codepen я использую Autoprefixer, который автоматически обрабатывает префиксы, специфичные для конкретного поставщика. для меня. Если бы я не использовал Autoprefixer, поскольку я использую Chrome, мне действительно нужно было бы использовать префикс -webkit в свойстве изображения маски, чтобы это работало правильно.

-webkit-mask-image

Но поскольку я использую Autoprefixer, мне не нужно этого делать. При добавлении масок в свои проекты следует учитывать только одну вещь.

Вот окончательный рабочий пример:

https://codepen.io/brianmtreese/pen/RwEVZRY?embedable=true

Использование SVG, linear-gradient и mask-image для создания краев неправильной формы

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

CSS mask-image example fadeout at top and bottom of a scrolling container with two linear-gradients

В этом примере у нас есть заголовок, который выглядит следующим образом:

Example of the demo site header before applying a CSS mask

И у нас есть нижний колонтитул, который выглядит так:

Example of the demo site footer before applying a CSS mask

Начнем с нашего заголовка. Как мы видели, mask-image очень похож на background-image, то есть мы можем использовать линейные градиенты, а также можем использовать реальные изображения. В этом случае мы собираемся использовать комбинацию SVG, функции url() и linear-gradient, чтобы замаскировать все остальное.

Начнем с функции url(). В этом примере мы будем использовать закодированный SVG, который очень похож на изображение в кодировке Base64. Вам действительно редко следует делать подобные вещи из соображений производительности, но в этом примере это будет отлично работать в нашей демонстрации Codepen.

header {
    mask-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 ...")
}

Свойство mask-size

Хорошо, теперь нам нужно добавить для этого mask-size, чтобы он имел правильный размер. Как и в предыдущем примере, нам также понадобится пара пользовательских свойств, потому что мы будем использовать их снова и снова в этом примере.

:root {
    --maskWidth: 62.5em; /* 1000px */
    --maskHeight: 3.125em; /* 50px */
}

Теперь, как и background-size, у нас есть свойство mask-size. Мы будем использовать наши пользовательские свойства для этого размера. Для ширины мы будем использовать --maskWidth, а для высоты — --maskHeight.

header {
    ...
    mask-size: var(--maskWidth) var(--maskHeight);
}

Свойство mask-position

Далее мы хотим, чтобы наше изображение располагалось внизу и в центре, поэтому, как и в случае с background-position, у нас есть свойство mask-position. И мы хотим использовать «низ» и «центр» для этой позиции.

header {
    ...
    mask-position: bottom center;
}

Свойство mask-repeat

Теперь мы хотим убедиться, что изображение не повторяется вдоль оси Y, а только вдоль оси X. Так же, как и background-repeat, у нас есть свойство mask-repeat. И мы будем использовать значение repeat-x.

header {
    ...
    mask-repeat: repeat-x;
}

Example of the demo site header with mask partially completed

Вот и все; оно начинает обретать форму.

Итак, теперь нам нужно использовать наш linear-gradient, чтобы замаскировать все, что находится над этим изображением, чтобы мы могли видеть наш фон. Мы начнем сверху со значения полностью непрозрачного черного цвета. Затем нам нужно, чтобы он был черным до тех пор, пока не встретится с верхом изображения маски, поэтому мы снова воспользуемся расчетом. Этот расчет будет равен 100 процентам минус высота нашей маски. И мы добавим значение в полпикселя, чтобы справиться с проблемами округления пикселей, которые иногда могут возникнуть. Это просто помогает гарантировать, что градиент будет совпадать с SVG или перекрывать его на один пиксель. Затем, при тех же вычислениях, мы хотим, чтобы наша маска была прозрачной, а затем снова прозрачной на 100 процентов.

header {
    ...
    mask-image: 
        ...
        linear-gradient(
            black,
            black calc(100% - var(--maskHeight) + 0.5px),
            transparent calc(100% - var(--maskHeight) + 0.5px),
            transparent
        );
}

Теперь единственная часть, которую нам не хватает, — это mask-size для нашего linear-gradient. В данном случае это будет 100 процентов.

header {
    ...
    mask-size: var(--maskWidth) var(--maskHeight), 100%;
}

В результате он будет распространяться на 100 процентов ширины и 100 процентов высоты этого прямоугольника.

Example of the demo site header with mask completed

Выглядишь неплохо, правда? Теперь мы можем сделать то же самое с нашим футером. Единственная разница в том, что мы используем другое изображение и значение градиента. Изображение перевернуто в направлении, противоположном нашему изображению заголовка, вверх. Затем наш градиент начинается с прозрачности высоты mask-image, а затем до конца становится черным. Он также расположен вверху и в центре.

footer {
    mask-image:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' ..."),
        linear-gradient(
            transparent 0%,
            transparent var(--maskHeight),
            black var(--maskHeight),
            black 100%
        );
    mask-size: var(--maskWidth) var(--maskHeight), 100%;
    mask-position: top center;
    mask-repeat: repeat-x;
}

Example of the demo site footer with mask completed

Итак, это дает нам хороший способ применять к коробкам различные эффекты. Вместо обычной прямой линии мы можем придать им более интересные эффекты с помощью масок CSS.

Вот окончательный рабочий пример:

https://codepen.io/brianmtreese/pen/XWoRaYe?embedable=true

Использование SVG и CSS mask-image для создания изображения шестиугольной формы

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

Example of a hexagonal SVG image to be used as a CSS mask

Хорошо, отличие этого подхода в том, что нам не нужен linear-gradient. Все, что нам нужно, это mask-image и наша функция url(). Давайте добавим наш закодированный SVG.

img {
    mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' ...");
}

Example of a hexagonal SVG mask applied bot not properly positioned

Ладно, это не совсем то, что нам нужно, эта маска выглядит немного причудливо. Нам нужно установить это значение так, чтобы оно не повторялось с помощью свойства mask-repeat. Кроме того, он немного смещен от центра, поэтому нам нужно отцентрировать его с помощью свойства mask-position.

img {
    ...
    mask-repeat: no-repeat;
    mask-position: center;
}

И вот мы идем. Это так просто.

Вот окончательный рабочий пример:

https://codepen.io/brianmtreese/pen/BavZagq?embedable=true

Заключение

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

Я надеюсь, что эти примеры вдохновят вас на то, чего можно добиться при использовании масок CSS. Ваша креативность – это все, что вас сейчас сдерживает.


Также опубликовано здесь.< /п>


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE