Как сделать фон на половину блока css
Перейти к содержимому

Как сделать фон на половину блока css

  • автор:

Background, занимающий половину длины

Как добавить background к элементу, который будет занимать половину контейнера (по длине)? Я могу это сделать с помощью linear-gradient :

.half-background
test text

Но этот способ мне не подходит. Есть ли другой способ?
Отслеживать
задан 26 июл 2017 в 17:30
user261263 user261263
11 1 1 серебряный знак 2 2 бронзовых знака
А почему не подходит вариант с градиентом?
27 июл 2017 в 13:10

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Вариант с использованием псевдоэлементов (:before, :after)

.half-background < position: relative; border: 1px solid #ccc; >.half-background:before
test text

Отслеживать
ответ дан 26 июл 2017 в 17:46
27.6k 5 5 золотых знаков 35 35 серебряных знаков 66 66 бронзовых знаков

Можно сделать изображение размером в 1 пиксель нужного цвета, положить его в background, задав ширину 50%, а еще задать цвет. Цвет зальёт весь блок, а однопиксельное изображение займет только половину. В сниппете однопиксельное изображение черного цвета задано инлайн через base64.

.half-background < border: 1px solid grey; background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=); background-size: 50% auto; background-color: cyan; background-repeat: no-repeat; >
test text

background-position

Задает начальное положение фонового изображения, установленного с помощью свойства background-image . В CSS3 допустимо указывать несколько значений для каждого фона, перечисляя значения через запятую.

Синтаксис

background-position: [left | center | right | | ] || [top | center | bottom | | ] | inherit
background-position: [, ]*

= [left | center | right | | ] || [top | center | bottom | | ] | inherit.

Значения

У свойства background-position два значения, положение по горизонтали (может быть — left , center , right ) и вертикали (может быть — top , center , bottom ). Кроме использования ключевых слов положение также можно задавать в процентах, пикселах или других единицах. Если применяются ключевые слова, то порядок их следования не имеет значения, при процентной записи вначале задается положение рисунка по горизонтали, а затем, через пробел, положение по вертикали. Отношение между используемыми ключевыми словами и процентной записью следующее.

  • top left = left top = 0% 0% (в левом верхнем углу)
  • top = top center = center top = 50% 0% (по центру вверху)
  • right top = top right = 100% 0% (в правом верхнем углу)
  • left = left center = center left = 0% 50% (по левому краю и по центру)
  • center = center center = 50% 50% (по центру)
  • right = right center = center right = 100% 50% (по правому краю и по центру)
  • bottom left = left bottom = 0% 100% (в левом нижнем углу)
  • bottom = bottom center = center bottom = 50% 100% (по центру внизу)
  • bottom right = right bottom = 100% 100% (в правом нижнем углу)

В скобках указано, где располагается фоновый рисунок относительно контейнера.

При inherit значение наследуется у родителя элемента.

XHTML 1.0 CSS2.1 IE Cr Op Sa Fx

    background-position   

.

HTML5 CSS3 IE Cr Op Sa Fx

    background-position   

Объектная модель

[window.]document.getElementById(» elementID «).style.backgroundPosition

Браузеры

Internet Explorer до версии 7.0 включительно не поддерживает значение inherit .

background — position

Фоновая картинка подчиняется этому свойству и занимает нужную позицию.

Время чтения: меньше 5 мин

Открыть/закрыть навигацию по статье

  1. Кратко
  2. Пример
  3. Как пишется
    1. Ключевые слова
    2. Пиксели или другие единицы измерения длины
    3. Проценты
    1. Алёна Батицкая советует

    Контрибьюторы:

    Обновлено 20 декабря 2021

    Кратко

    Скопировать ссылку «Кратко» Скопировано

    При помощи свойства background — position можно управлять положением фоновой картинки внутри элемента.

    Если фоновая картинка ( background — image ) меньше, чем элемент, и автоматическое повторение фона ( background — repeat ) отключено, то по умолчанию она расположится в левом верхнем углу.

    Пример

    Скопировать ссылку «Пример» Скопировано

     div class="element">div>      
     .element  background-color: #49a16c; background-image: url("doggo.png"); background-repeat: no-repeat;> .element  background-color: #49a16c; background-image: url("doggo.png"); background-repeat: no-repeat; >      

    Как видно в примере, маленькая картинка с персонажем располагается в левом верхнем углу. Но по логике это изображение нам нужно расположить в правом нижнем углу.

    Для этого мы изменим значение свойства background — position на нужное нам: 100 % 100 % или bottom right . Они равнозначны.

    Позиция в процентах:

     .element  background-position: 100% 100%;> .element  background-position: 100% 100%; >      

    Или при помощи ключевых слов:

     .element  background-position: bottom right;> .element  background-position: bottom right; >      

    Как пишется

    Скопировать ссылку «Как пишется» Скопировано

    Ключевые слова

    Скопировать ссылку «Ключевые слова» Скопировано

    Доступны слова center , bottom , left , right . Их можно комбинировать, например: left center — по центру левой стороны; right bottom — правый нижний угол. Если хотим расположить картинку по центру по горизонтали и вертикали, второе слово center можно опустить.

    Левый верхний угол:

     .element  background-position: left top;> .element  background-position: left top; >      
     .element  background-position: center;> .element  background-position: center; >      

    По центру по горизонтали и у нижнего края:

     .element  background-position: center bottom;> .element  background-position: center bottom; >      

    Пиксели или другие единицы измерения длины

    Скопировать ссылку «Пиксели или другие единицы измерения длины» Скопировано

    Можно указать конкретное положение картинки в блоке.

    10 px от левого края и 150 px от верхнего края:

     .element  background-position: 10px 150px;> .element  background-position: 10px 150px; >      

    1 rem от левого края и по центру между верхом и низом:

     .element  background-position: 1rem;> .element  background-position: 1rem; >      

    15 единиц ширины от левого края и 25 единиц высоты от верха:

     .element  background-position: 15vw 25vh;> .element  background-position: 15vw 25vh; >      

    Проценты

    Скопировать ссылку «Проценты» Скопировано

    Для этого свойства проценты рассчитываются необычным для CSS образом: от разницы между размером элемента и размером самой фоновой картинки. Сдвиг картинки на 50 % , то есть на половину этой разницы, центрирует её по соответствующей оси. Значение 0 % 0 % ставит картинку в левый верхний угол, а 100 % 100 % — в правый нижний.

    Правый нижний угол:

     .element  background-position: 100% 100%;> .element  background-position: 100% 100%; >      
     .element  background-position: 50% 50%;> .element  background-position: 50% 50%; >      

    Слева 15%, сверху 5%:

     .element  background-position: 15% 5%;> .element  background-position: 15% 5%; >      

    Если развернуть запись 15 % 5 % подробнее, то станет понятнее, как работают проценты в этом случае:

    • Слева от картинки 15% свободного места, а справа — оставшиеся 85%.
    • Над картинкой 5% свободного места, а под ней — оставшиеся 95%.

    Подсказки

    Скопировать ссылку «Подсказки» Скопировано

    �� Свойство положения фона не наследуется.

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

    �� Значение по умолчанию — 0% 0% (левый верхний угол).

    �� Если указано только одно значение, то второе подставляется автоматически и равняется 50 % . То есть значение 100 % расположит картинку по центру правого края.

    �� Если картинка больше блока, то разница их размеров, от которой отсчитываются проценты, оказывается отрицательной, поэтому они сдвигают картинку не вправо и вниз, а влево и вверх. Но 50 % 50 % и в этом случае совмещает центр картинки с центром элемента, а 100 % 100 % — правый нижний угол картинки с правым нижним углом элемента.

    �� Если картинка занимает всё пространство блока, то background — position с ключевыми словами или в процентах не возымеет никакого действия (проценты будут отсчитываться от нуля). Но его принято указывать, чтобы в случае замены картинки новое изображение располагалось по центру блока.

    �� Изменение положения фона можно анимировать при помощи свойства transition ��

    На практике

    Скопировать ссылку «На практике» Скопировано

    Алёна Батицкая советует

    Скопировать ссылку «Алёна Батицкая советует» Скопировано

    �� В работе редко требуется располагать маленькие фоновые картинки в больших блоках. Сейчас принято делать красивые фоны на всю ширину. Но для любых фонов стоит указывать background — position : center или background — position : 50 % 50 % — в качестве подстраховки от фатальной поломки вёрстки.

    �� Можно встретить такую запись: background — position : right 20px bottom 10px; . В этом случае отступ будет отсчитываться не от верхнего левого угла, а от указанной при помощи ключевого слова стороны. В данном случае картинка будет расположена в двадцати пикселях от правого края и в десяти пикселях от нижнего края.

    �� Помимо перечисленных вариантов можно использовать функцию calc ( ) для указания более гибкого значения.

    Свойство background-clip и его применения

    background-clip — одно из тех свойств, о которых я давно знала, но почти не использовала. Может, лишь пару раз в ответах на Stack Overflow. До прошлого года, когда я начала создавать эту огромную коллекцию ползунковых регуляторов (слайдеров). Некоторые дизайны, что я решила воспроизвести, были довольно-таки сложны, а мне на каждый ползунок отводился один-единственный элемент, и им как назло оказался input , к которому даже псевдоэлементов толком не добавить. Хоть в некоторых браузерах такое и работает, то, что оно работает — на самом деле баг, и мне не хотелось на это полагаться. Так что в итоге мне пришлось использовать фоны, рамки и тени в изобилии. И я многому научилась при этом, и в этой статье делюсь некоторыми их тех уроков.

    Первым делом давайте посмотрим, что такое background-clip и что оно делает.

    На следующей картинке у нас блочная (или всё-таки боксовая? — прим. перев.) модель элемента.

    Если padding равен 0 , то padding-box по размеру точно равен content-box , и край контента совпадает с краем внутреннего отступа.

    Если border-width равен 0 , то border-box по размеру точно равен padding-box , и край рамки совпадает с краем внутреннего отступа.

    Если и padding , и border-width оба равны 0 , то все три области ( content-box , padding-box и border-box ) равны по размеру, и края контента, внутреннего отступа и рамки все совпадают друг с другом.

    По умолчанию фоны покрывают всю border-box (под рамкой они тоже накладываются), но их background-position (а также проценты для background-size ) отсчитываются от padding-box .

    Чтобы лучше это понять, рассмотрим пример. Возьмем блок с наугад выбранными размерами, зададим ему простой градиентный фон с background-size: 50% 50% и заштрихованный border (с помощью border-image ), так что сквозь штрихи нам будет видно, что там под рамкой:

    В этом примере видно, что градиентный фон целиком покрывает border-box (его видно под штрихованной рамкой). Мы не указывали ему background-position , так что у него значение по умолчанию — 0 0 . Видно, что оно отсчитывается от padding-box , потому что начинается от левого верхнего угла (точки 0 0 ) этой области. Видно также, что background-size , указанный в процентах, отсчитывается от padding-box .

    Задавая background-size для градиентов (но не для настоящих картинок), мы обычно вынуждены указывать два значения ради единообразия результата в браузерах. Если указать лишь одно значение, то второе в Firefox станет равным 100% (по спецификации), тогда как все остальные браузеры ошибочно делают второе значение равным первому. Пропущенное значение background-size принимается за auto , и так как у градиентов нет внутренних размеров и пропорций, значение auto никак из них не высчитать, так что оно должно восприниматься как 100% . Поэтому, если только мы не собираемся растягивать background-size на 100% по обоим измерениям, нам понадобятся два значения.

    Можно заставить фон покрывать только padding-box или только content-box с помощью background-clip . Обрезка (clipping) означает, что всё, что выступает за обрезаемую область, отсекается и не показывается. Обрезаемой областью на иллюстрации ниже будет то, что лежит внутри пунктирной линии.

    При background-clip: border-box (по умолчанию) обрезаемой областью будет border-box , так что у нас будет фон и под рамкой.

    Если задать background-clip: padding-box , обрезаемой областью будет padding-box , так что фон будет отображаться только в пределах padding-box (под рамкой его уже не будет).

    И наконец, при background-clip: content-box обрезаемой областью будет content-box , так что фон будет показан только в пределах content-box .

    Эти три случая показаны в следующем живом примере:

    У нас есть и еще одно свойство под названием background-origin , которое указывает, от какой из трех областей отсчитывается background-position (и background-size , если выражен в процентах).

    Допустим, у нас опять есть элемент с заштрихованным border , но, на этот раз, с видимым padding . Положим на фон обычную картинку и градиент. У обоих background-size: 50% 50% , и оба они не повторяются. В добавок к этому, у картинки будет background-position: 100% 100% (а для градиента оставим 0 0 по умолчанию):

    background: linear-gradient(to right bottom, #e18728, #be4c39, #9351a6, #4472b9), url(tiger_lily.jpg) 100% 100%; background-repeat: no-repeat; background-size: 50% 50%;

    Следующий пример показывает, что происходит при каждом из трех возможных значений background-origin — border-box , padding-box и content-box :

    Значение 100% 100% , указанное для background-position настоящей картинки — это 100% 100% от области, указанной в background-origin . В то же время, 50% 50% , указанные для background-size , означают половину ширины и половину высоты области, указанной в background-origin .

    В сокращенной записи background свойства background-origin и background-clip можно указывать именно в таком порядке в конце слоя. Поскольку они оба принимают значение вида *- box , то если указать лишь одно значение такого типа, оно будет присвоено сразу им обоим. Если указать два значения, background-origin получит первое, а background-clip — второе. Если не указывать значений вида *- box , оба свойства останутся со своими значениями по умолчанию ( padding-box для background-origin и border-box для background-clip ).

    Чудесно! Посмотрим теперь, как использовать это в своих интересах!

    Прозрачный зазор между рамкой и фоном

    Кто-то наверняка вспомнит, что с background-clip можно делать полупрозрачные рамки. Но можно еще и добавить зазор между рамкой и областью, покрытой фоном, без дополнительного элемента. Простейший способ этого добиться — задать padding в дополнение к border и указать для background-clip значение content-box . Если сделать это сокращенной записью с единственным значением content-box , мы заодно установим значение content-box и для background-origin , но в данном случае это нормально, никаких побочных эффектов от него нет.

    border: solid .5em #be4c39; padding: .5em; background: #e18728 content-box;

    Обрезка фона по content-box значит, что он не распространится за края контента. Дальше их фона не будет, так что будет видно всё, что находится под нашим элементов. Добавка border значит, что мы увидим этот border в между краем внутреннего отступа и краем рамки. Но, поскольку padding ненулевой, у нас остается прозрачная область между краями контента и внутреннего отступа.

    Можно проверить это вживую в этом примере на CodePen:

    Можно сделать результат еще интереснее, добавив фильтр drop-shadow() , который добавит всей конструкции желтоватое свечение:

    Напоминание насчет префиксов: я видела множество ресурсов, добавляющих префиксы -moz- и -ms- для CSS-фильтров. Пожалуйста, не делайте этого! CSS-фильтры работают в Firefox без префикса с тех самых пор, как их там реализовали (Firefox 34, осенью 2014-го), а сейчас они появились в Edge за флагом — и тоже без префикса! Так что CSS-фильтрам никогда не были нужны префиксы -moz- и -ms- , добавлять их абсолютно бессмысленно, они будут лишь загромождать стили мертвым грузом.

    Можно также получить клёвый визуальный эффект, применив градиент и для background-image , и для border-image . Сделаем градиент, начинающийся со сплошного оранжево-красного цвета вверху и переходящий в полную прозрачность внизу. Поскольку различаются лишь оттенки, а в остальном наши градиенты идентичны, создадим функцию Sass.

    @function fade($c) < return linear-gradient($c, rgba($c, 0) 80%); >div

    Можно проверить это в действии в этом примере на CodePen:

    Этот подход, когда в качестве пустого пространства между фоном и рамкой служит внутренний отступ, трудно назвать лучшим, если только внутри не одна коротенькая надпись. Если текста больше… да уж, смотрится это паршиво.

    Загвоздка в том, что текст начинается сразу от края оранжевого фона, а мы не можем добавить внутренний отступ, ведь он уже занят под прозрачный зазор. Можно было бы добавить лишний элемент… а можно воспользоваться box-shadow !

    box-shadow может принимать 2 , 3 либо 4 значения длины. Первое — смещение по x (определяющее, насколько сдвинуть тень вправо), второе — смещение по y (насколько сдвинуть тень вниз), третье — радиус размытия (определяет, насколько будет размыт край тени), и четвертое — радиус распространения (определяет, как далеко тень будет простираться во все стороны).

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

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

    Еще одна важная вещь, которую здесь надо отметить — поскольку она удобна для нашей задачи — то, что box-shadow никогда не отображается под border-box , даже когда эта область (полу)прозрачна.

    Если оставить смещения и размытие нулевыми, но задать положительное значение радиусу распространения, то с виду получится вторая сплошная рамка одинаковой со всех сторон толщины, наружу от края настоящей рамки.

    Обратите внимание, что такие рамки не обязательно должны быть одинаковой толщины со всех сторон. Можно придать их сторонам разную толщину, подгоняя значения смещений и радиуса распространения, с тем ограничением, что суммарная толщина вертикальных границ должна равняться суммарной толщине горизонтальных. Если рамке не нужна полупрозрачность, то и это ограничение можно обойти с помощью нескольких теней, но подобное решение уже скорее не упростит, а усложнит нам работу.

    Возвращаясь к нашему примеру, можно имитировать рамку с помощью box-shadow с распространением, реальный border превратить в прозрачный зазор, задать для background-clip значение padding-box , и применить padding по назначению:

    border: solid 1em transparent; padding: 1em; box-shadow: 0 0 0 1em #be4c39; background: #e18728 padding-box;

    Это можно посмотреть в действии в следующем примере на CodePen:

    Можно было бы имитировать рамку и внутренней тенью (с параметром inset ). В этом случае она начинается от края внутреннего отступа (границы между областями padding и border ), и распространяется на указанный радиус внутрь.

    эмуляция второй рамки с помощью внутренней box-shadow

    Поскольку теней может быть много, так можно имитировать несколько рамок. Пусть, к примеру, их у нас две, причем одна из них — inset . Если реальный border элемента ненулевой толщины и при этом transparent , а у background-clip стоит значение padding-box , то получится имитация двойной рамки с прозрачной областью (на месте реальной рамки) между внешней и внутренней частями. Обратите внимание, что ради этого понадобилось увеличить padding для компенсации места, занятого внутренней box-shadow .

    border: solid 1em transparent; padding: 2em; // увеличен с 1em до 2em для компенсации внутреннего "border" box-shadow: 0 0 0 0.25em #be4c39 /* внешний "border" */, inset 0 0 0 1em #be4c39 /* внутренний "border" */; background: #e18728 padding-box;

    Можно испытать это в действии в этом примере на CodePen, где добавлен еще фильтр drop-shadow() для «светящегося» эффекта.

    Мишень из одного элемента (без псевдоэлементов) с гладкими краями

    Допустим, нам нужно получить вот такую мишень, и при этом нам позволено использовать только один элемент без псевдоэлементов.

    Первая мысль — воспользоваться repeating-radial-gradient . Структура нашей мишени примерно такая:

    Итак, половина мишени составит 9 единиц, т.е. размеры мишени по вертикали и горизонтали будут по 18 единиц. Наш повторяющийся радиальный градиент всю первую единицу черный, потом до третьей единицы (включительно — прим. перев.) прозрачный, потом опять черный и опять прозрачный… звучит как повторение. Вот только первый раз у нас черная область от 0 до 1, т.е. одна единица, а следующая черная область уже от 3 до 5 — две единицы! Так что… нам тут надо начать отсчет не от 0 , а от -1 , верно? Что ж, это должно работать, согласно спецификации.

    $unit: 1em; background: repeating-radial-gradient( #000 (-$unit), #000 $unit, transparent $unit, transparent 3*$unit );

    Этот пример на CodePen иллюстрирует принцип:

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

    К счастью, это исправили в Edge, но если нужна поддержка IE, проблема остается. Ее можно решить, используя обычный радиальный градиент, нам ведь всё равно не так уж много кругов и нужно. Кода больше, но всё не так уж плохо…

    background: radial-gradient( #000 $unit, transparent 0, transparent 3*$unit, #000 0, #000 5*$unit, transparent 0, transparent 7*$unit, #000 0, #000 9*$unit, transparent 0 );

    Можно увидеть его в действии в этом примере на CodePen:

    Теперь окружности распределены во всех браузерах одинаково, но у нас осталась другая проблема: пусть края не слишком отличаются по гладкости от оригинальной картинки в IE/Edge, но в Firefox и Chrome они выглядят просто ужасно!

    background: radial-gradient( #000 calc(# - 1px), transparent $unit, transparent calc(# - 1px), #000 3*$unit, #000 calc(# - 1px), transparent 5*$unit, transparent calc(# - 1px), #000 7*$unit, #000 calc(# - 1px), transparent 9*$unit );

    Что ж, в IE (где и так было неплохо) и Firefox стало лучше, но в Chrome края по-прежнему безобразные.

    Может быть, радиальные градиенты вообще не лучшее решение, в конце концов. А почему бы нам не приспособить сюда решение на background-clip и box-shadow из предыдущего раздела? С помощью внешней box-shadow мы можем сделать внешнее кольцо, а тенью с inset — внутреннее. Пространство между ними займет прозрачная рамка. Мы также установим для background-clip значение content-box и дадим элементу достаточный внутренний отступ, так что у нас получится прозрачная область между центральным кружком и внутренним кольцом.

    border: solid 2*$unit transparent; padding: 4*$unit; width: 2*$unit; height: 2*$unit; border-radius: 50%; box-shadow: 0 0 0 2*$unit #000, inset 0 0 0 2*$unit #000; background: #000 content-box;

    Посмотрите, как это работает, в следующем примере на CodePen, никаких «рваных» краев и прочих неприятностей:

    Реалистичные элементы управления

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

    Для полосы у нас есть -webkit-slider-runnable-track , -moz-range-track и -ms-track . Для ручки — -webkit-slider-thumb , -moz-range-thumb и -ms-thumb . И для заполненной части есть -moz-range-progress , -ms-fill-lower (оба для части слева от ручки) и -ms-fill-upper (справа от ручки). У WebKit-браузеров не предусмотрено псевдоэлемента, которым можно было бы оформить части ползунка до и после ручки по-разному.

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

    input[type='range']::-webkit-slider-thumb, input[type='range']::-moz-range-thumb, input[type='range']::-ms-thumb < /* styles here */ >

    Нам приходится постоянно писать их так:

    input[type='range']::-webkit-slider-thumb < /* styles here */ >input[type='range']::-moz-range-thumb < /* styles here */ >input[type='range']::-ms-thumb < /* styles here */ >

    Что выглядит как механическое «переливание» в коде одной и той же «воды», и часто это так и есть — хотя при таком обилии разночтений между браузерами, как с ползунками, такие дубликаты полезны для сглаживания этих различий. Моим решением было использовать миксин thumb() и при необходимости передавать ему аргументы для обработки несоответствий. Например, как-то так:

    @mixin thumb($flag: false) < /* styles */ @if $flag < /* more styles */ >> input[type='range'] < &::-webkit-slider-thumb < @include thumb(true); >&::-moz-range-thumb < @include thumb(); >&::-ms-thumb < @include thumb(); >>

    Но вернемся к самим возможностям оформления. Добавлять псевдоэлементы к этим деталям можно только в Chrome и Opera, а это значит, что нам нужно будет максимально точно, как только возможно, воспроизвести их внешний вид, не полагаясь на псевдоэлементы. Так что у нас остаются только фоны, рамки, тени и фильтры для самого «элемента» ручки.

    Давайте взглянем на несколько примеров!

    Мягкий пластик

    В качестве визуального примера представим себе что-то вроде ручки ползунка ниже:

    На первый взгляд всё решение сводится к градиентному background и и градиенту для border-image , потом еще box-shadow для красоты — и такой элемент готов:

    border: solid 0.375em; border-image: linear-gradient(#fdfdfd, #c4c4c4) 1; box-shadow: 0 0.375em 0.5em -0.125em #808080; background: linear-gradient(#c5c5c5, #efefef);

    И это даже работает (на примере элемента button вместо ручки ползунка ради простоты):

    За исключением того, что наша ручка круглая, а не квадратная. Нужно просто добавить ей border-radius: 50% , так? Так вот… это не сработает, потому что мы используем border-image , с которым border-radius самого элемента игнорируется, хотя, как это ни забавно, он по-прежнему действует на box-shadow , если она есть.

    Что же делать? Точно, использовать background-clip ! Сначала мы зададим элементу ненулевой padding , уберем рамку и скруглим его с помощью border-radius: 50% . Затем наложим два градиентных фона, обрезав верхний по content-box (обратите внимание, что обрезка входит в сокращенную запись background) . Наконец, добавим две тени, одну темную, создающую собственно тень под ручкой, а вторую с inset , которая будет слегка затемнять низ и бока внешней части ручки.

    border: none; /* makes border-box ≡ padding-box */ padding: .375em; border-radius: 50%; box-shadow: 0 .375em .5em -.125em #808080, inset 0 -.25em .5em -.125em #bbb; background: linear-gradient(#c5c5c5, #efefef) content-box, linear-gradient(#fdfdfd, #c4c4c4);

    Полюбоваться конечным результатом можно в этом примере на CodePen:

    Матовая ручка

    Что-то вроде ручки ползунка со следующей картинки:

    Этот случай похож на предыдущий, только теперь у нас светлая линия вверху и внутренняя тень для средней части. Если использовать внешнюю box-shadow для создания светлой линии, вся конструкция потеряет круглую форму, если только заодно не уменьшить высоту для компенсации тени. А тогда потребуется больше расчетов для определения положения внутренней части. Если же сделать ее тенью с inset , то мы уже не сможем использовать ее для затемнения внутренней части. Однако, мы можем эмулировать ее с помощью radial-gradient , которому заданы подходящий размер, положение и обрезка по content-box . То есть делаем всё аналогично предыдущему примеру, но теперь у нас поверх остальных фонов будет наложен дополнительный radial-gradient . Фактический background-size этого радиального градиента больше, чем наш content-box , так что мы можем сдвинуть его вниз так, что его верхний край останется за пределами области контента.

    border: none; /* теперь border-box ≡ padding-box */ padding: .625em; width: 1.75em; height: 1.75em; border-radius: 50%; box-shadow: 0 1px .125em #444 /* темная тень внизу */, inset 0 1px .125em #fff /* светлый блик наверху */; background: /* эффект внутренней тени */ radial-gradient(transparent 35%, #444) 50% calc(50% + .125em) content-box, /* внутренний фон */ linear-gradient(#bbb, #bbb) content-box, /* внешний фон */ linear-gradient(#d0d3d5, #d2d5d7); background-size: 175% 175% /* размер с запасом для радиального градиента */, 100% 100%, 100% 100%;

    Можно посмотреть на это вживую в этом примере на Code Pen:

    Объемный элемент

    Например, ручка следующего ползунка:

    Это уже посложнее, для этого все три области ( content-box , padding-box и border-box ) должны быть разными, чтобы мы могли накладывать фоны друг на друга и добиваться нужного эффекта с помощью background-clip .

    Итак, для основной части ползунка у нас есть градиентный background , обрезанный по content-box , наложенный поверх другого, обрезанного по padding-box , и оба они поверх третьего linear-gradient , обрезанного по border-box . Мы таже задействовали внутреннюю box-shadow , чтобы подчеркнуть край внутреннего отступа (между padding и border ):

    border: solid .25em transparent; padding: .25em; border-radius: 1.375em; box-shadow: inset 0 1px 1px rgba(#f7f7f7, .875) /* сверху */, inset 0 -1px 1px rgba(#bbb, .75) /* снизу */; background: linear-gradient(#9ea1a6, #fdfdfe) content-box, linear-gradient(#fff, #9c9fa4) padding-box, linear-gradient(#eee, #a4a7ab) border-box;

    Результат можно посмотреть на CodePen здесь:

    See the Pen 3D button by Ana Tudor (@thebabydino) on CodePen.

    Теперь остается маленькая круглая деталька. Это тот случай, когда я по-настоящему почувствовала потребность в псевдоэлементе. В итоге я и пошла по этому пути для Blink, но мне удалось сделать так, что запасной вариант для других браузеров — из наложенных друг на друга двух радиальных градиентов поверх линейных — стал выглядеть прилично:

    Можно было бы еще приблизиться к нашей цели, лучше подобрав оттенки, добавив еще радиальных градиентов или даже воспользовавшись background-blend-mode , но на подобное мне не хватает художественного чутья.

    С псевдэлементом добиться нужного результата намного проще — сначала нужно задать ему правильные размер и положение, закруглить его с помощью border-radius: 50% . Затем задать ему padding , никакой рамки, и использовать два градиента в background , верхний из которых радиальный и обрезан по content-box :

    padding: .125em; background: radial-gradient(circle at 50% 10%, #f7f8fa, #9a9b9f) content-box, linear-gradient(#ddd, #bbb);

    Посмотреть, что получилось, можно в следующем примере:

    Для ручки реального ползунка я использовала тот же самый background с радиальными градиентами сверху для всех браузеров, а для Blink добавила псевдоэлемент прямо поверх этих радиальных градиентов. Это потому, что стили ручки ползунка в Safari применяются к ::-webkit-slider-thumb , но Safari не поддерживает псевдоэлементов для ручки (или дорожки). Так что если бы я убрала запасной вариант из стилей для ::-webkit-slider-thumb , то Safari не отобразил бы круглую детальку вообще.

    Иллюзия глубины

    Дорожка следующего ползунка иллюстрирует основную мысль:

    Как и раньше, для этого мы задаем элементу ненулевой прозрачный border , padding , и накладываем друг на друга фоны с разными значениями background-clip (помните, что слои со значением content-box должны лежать поверх слоев со значением padding-box , а те — поверх слоев со значением border-box ). В данном случае у нас есть более светлый linear-gradient для заливки области border , более темный — плюс пара уменьшенных неповторяющихся радиальных, чтобы добавить еще темноты по краям — для области padding , и совсем тёмный для области контента. Затем мы задаем этой конструкции border-radius , равный как минимум половине от суммы height области контента, удвоенного padding и удвоенного border . И еще добавим внутреннюю box-shadow , чтоб слегка подчеркнуть край внутреннего отступа.

    border: solid .375em transparent; padding: 1em 3em; width: 15.75em; height: 1.75em; border-radius: 2.25em; background: linear-gradient(#090909, #090909) content-box, radial-gradient(at 5% 40%, #0b0b0b, transparent 70%) no-repeat 0 35% padding-box /* левый край */, radial-gradient(at 95% 40%, #111, transparent 70%) no-repeat 100% 35% padding-box /* правый край */, linear-gradient(90deg, #3a3a3a, #161616) padding-box, linear-gradient(90deg, #2b2d2c, #2a2c2b) border-box; background-size: 100%, 9em 4.5em, 4.5em 4.5em, 100%, 100%;

    Но тут есть проблема, и ее видно в следующем примере на CodePen:

    Из-за того, как работает border-radius — радиус области контента получается из указанного вычитанием border-width и padding , что дает в итоге отрицательное число — углы области контента не закругляются. Что ж, мы можем это исправить! Можно эмулировать нужную нам форму, сочетая линейные, и радиальные градиенты для области контента.

    Делается это так: сначала убедимся, что width нашей области контента кратна ее height (в нашем случае, 15.75em = 9*1.75em ). Нижним слоем положим linear-gradient по центру так, чтобы по вертикали он покрывал всю height области контента, но оставляет зазоры по половине ее height от обоих боковых краев. Поверх него накладываем radial-gradient , background-size , равным height области контента и по горизонтали, и по вертикали.

    Металлические элементы управления

    Например, что-то вроде кнопки, изображенной ниже:

    Это уже чуть сложнее, так что давайте разберем его по частям. Прежде всего, мы делаем кнопку круглой, задав ей равные width и height и установив border-radius: 50% . Затем убеждаемся, что ей задан box-sizing: border-box , чтобы border-width и padding отсчитывались внутрь (вычитались из размеров, что мы указали). Теперь зададим ей прозрачную рамку и внутренний отступ. И вот что у нас получилось на данный момент:

    $d-btn: 27em; /* диаметр кнопки */ $bw: 1.5em; /* border-width */ button

    Пока еще это ни на что не похоже, потому что весь общий вид достигается с помощью двух свойств, которые мы еще не добавили: box-shadow и background .

    Прежде чем двигаться куда-то дальше, давайте немного разберем, из чего состоит элемент:

    В порядке от самой внешней детали к центру, у нас есть:

    • широкое внешнее кольцо со светодиодами
    • тонкое внутреннее кольцо
    • решетчатая область (она же включает в себя голубое свечение вокруг следующей внутренней части)
    • большая центральная деталь

    Широкое внешнее кольцо — это область рамки, центральная часть — область контента, а всё, что между ними (тонкое внутреннее кольцо и решетчатая часть) — область внутреннего отступа. Тонкое внутреннее кольцо мы сделаем внутренней тенью:

    box-shadow: /* прерывистая темная тень, отделяющая от внешнего кольца */ inset 0 0 1px #666, /* темная область вверху */ inset 0 1px .125em #8b8b8b, inset 0 2px .25em #a4a2a3, /* темная область внизу */ inset 0 -1px .125em #8b8b8b, inset 0 -2px .25em #a4a2a3, /* основная полоса по окружности внутреннего кольца */ inset 0 0 0 .375em #cdcdcd;

    Добавим еще две внешних тени, одну для светлого верхнего блика на внешнем кольце и другую для кусочка темной тени под элементом, итого у нас уже есть:

    box-shadow: 0 -1px 1px #eee, 0 2px 2px #1d1d1d, inset 0 0 1px #666, inset 0 1px .125em #8b8b8b, inset 0 2px .25em #a4a2a3, inset 0 -1px .125em #8b8b8b, inset 0 -2px .25em #a4a2a3, inset 0 0 0 .375em #cdcdcd;

    До цели еще далековато, но уже хоть что-то.

    Теперь нам нужно наложить друг на друга три типа фонов, сверху вниз: ограниченный по content-box (образующий центральную область), ограниченный по padding-box (образующий решетчатую область и голубое свечение) и ограниченный по border-box (образующий широкое внешнее кольцо и светодиоды).

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

    background: /* ======= content-box ======= */ /* окружности - используем простые числа 13, 19, 23 */ repeating-radial-gradient( rgba(#e4e4e4, 0) 0, rgba(#e4e4e4, 0) 23px, rgba(#e4e4e4, .05) 25px, rgba(#e4e4e4, 0) 27px) content-box, repeating-radial-gradient( rgba(#a6a6a6, 0) 0, rgba(#a6a6a6, 0) 13px, rgba(#a6a6a6, .05) 15px, rgba(#a6a6a6, 0) 17px) content-box, repeating-radial-gradient( rgba(#8b8b8b, 0) 0, rgba(#8b8b8b, 0) 19px, rgba(#8b8b8b, .05) 21px, rgba(#8b8b8b, 0) 23px) content-box, /* конические отражения */ conic-gradient(/* случайные варианты нескольких оттенков серого */ #cdcdcd, #9d9d9d, #808080, #bcbcbc, #c4c4c4, #e6e6e6, #dddddd, #a1a1a1, #7f7f7f, #8b8b8b, #bfbfbf, #e3e3e3, #d2d2d2, #a6a6a6, #858585, #8d8d8d, #c0c0c0, #e5e5e5, #d6d6d6, #9e9e9e, #828282, #8f8f8f, #bdbdbd, #e3e3e3, #cdcdcd) content-box;

    И наконец это становится на что-то похоже!

    Переходим к решетчатой области. Голубое свечение — просто радиальный градиент, сходящий к краям в прозрачность, а вот в основе отверстий лежит паттерн «Карбоновое волокно» из галереи, которую Лиа Веру сделала целых пять лет назад — но всё еще чертовски полезной для людей с ограниченными художественными способностями вроде меня.

    $d-hole: 1.25em; /* диаметр отверстий */ $r-hole: .5*$d-hole; /* радиус отверстий */ background: /* ======= padding-box ======= */ /* голубое свечение */ radial-gradient( #00d7ff 53%, transparent 65%) padding-box, /* отверстия */ radial-gradient( #272727 20%, transparent 25%) 0 0 / # # padding-box, radial-gradient( #272727 20%, transparent 25%) $r-hole $r-hole / # # padding-box, radial-gradient(#444 20%, transparent 28%) 0 .125em / # # padding-box, radial-gradient(#444 20%, #3d3d3d 28%) # # / # # padding-box

    Кажется, у нас начинает вырисовываться что-то приличное:

    Основа широкого внешнего кольца (без светодиодов) делается одним коническим градиентом:

    conic-gradient( #b5b5b5, #8d8d8d, #838383, #ababab, #d7d7d7, #e3e3e3, #aeaeae, #8f8f8f, #878787, #acacac, #d7d7d7, #dddddd, #b8b8b8, #8e8e8e, #848484, #a6a6a6, #d8d8d8, #e3e3e3, #8e8e8e, #868686, #a8a8a8, #d5d5d5, #dedede, #b5b5b5) border-box;

    И вот у нас получился металлический элемент!

    Но на нем пока нет светодиодов, исправим же это поскорее!

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

    Включенными у нас будут светодиоды вплоть до $k -того. Так что до этой отметки используем голубой вариант верхнего градиента, а после нее — серый.

    У нас 24 светодиода, размещенных по окружности, проходящей по середине области рамки. Так что ее радиус — это радиус элемента минус половина толщины рамки.

    Будем генерировать все эти градиенты с помощью Sass. Сначала создадим пустой список градиентов, затем пройдемся по нему циклом и на каждой итерации будем добавлять в список два градиента. Их координаты рассчитаны так, что они окажутся на вышеупомянутой окружности. Первый градиент зависит от счетчика цикла, а второй всегда одинаков (разве что с другими координатами на окружности).

    $d-btn: 27em; $bw: 1.5em; $r-pos: .5*($d-btn - $bw); $n-leds: 24; $ba-led: 360deg/$n-leds; $d-led: 1em; $r-led: .5*$d-led; $k: 7; $leds: (); @for $i from 0 to $n-leds < $a: $i*$ba-led - 90deg; $x: .5*$d-btn + $r-pos*cos($a) - $r-led; $y: .5*$d-btn + $r-pos*sin($a) - $r-led; $leds: $leds, if($i < $k, (radial-gradient(circle, #01d6ff, #178b98 .5*$r-led, rgba(#01d6ff, .35) .7*$r-led, rgba(#01d6ff, 0) 1.3*$r-led) no-repeat ## / # # border-box), (radial-gradient(circle, #898989, #4d4d4d .5*$r-led, #999 .65*$r-led, rgba(#999, 0) .7*$r-led) no-repeat $x $y / # # border-box) ), radial-gradient(circle, rgba(#e8e8e8, .5) .5*$r-led, rgba(#e8e8e8, 0) .7*$r-led) no-repeat $x ($y + .125em) / # # border-box; >

    Окончательным результатом можно полюбоваться в этом примере:

    Тени на перпендикулярной плоскости

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

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

    Наложение фонов с разными значениями background-clip и background-origin выручает и в этом случае. Саму кнопку мы строим двумя фонами, верхний из которых обрезан по content-box , а тот, что под ним — по padding-box , и используем фоновый radial-gradient() со значением border-box для background-clip и background-origin , чтобы сделать тень.

    Базовое оформление очень похоже на оформление металлического элемента из прошлого раздела:

    $l: 6.25em; $bw: .1*$l; border: solid $bw transparent; padding: 3px; width: $l; height: $l; border-radius: 1.75*$bw;

    Мы задаем довольно широкую прозрачную рамку вокруг кнопки, чтобы нам хватило места для создания этой тени в нижней части рамки. Делаем это для всех сторон рамки, а не только для нижней, потому что нам нужно, чтобы все углы у padding-box закруглялись одинаково и симметрично (если вам нужно освежить в памяти, как это работает, посмотрите потрясающий доклад о border-radius Лии Веру).

    Первый background наверху — это conic-gradient() для создания металлического отлива. Он обрезан по content-box . Прямо под ним у нас linear-gradient() , обрезанный по padding-box . Мы используем три внутренние тени, чтобы сделать этот второй фон менее плоским — добавляем еще один оттенок вокруг него с нулевым размытием, осветляем его вверху полупрозрачной белой тенью и затемняем внизу полпрозрачной черной тенью.

    box-shadow: inset 0 0 0 1px #eedc00, inset 0 1px 2px rgba(#fff, .5), inset 0 -1px 2px rgba(#000, .5); background: conic-gradient( #edc800, #e3b600, #f3cf00, #ffe800, #ffe900, #ffeb00, #ffe000, #ebc500, #e0b100, #f1cc00, #fcdc00, #ffe500, #fad900, #eec200, #e7b900, #f7d300, #ffe800, #ffe300, #f5d100, #e6b900, #e3b600, #f4d000, #ffe400, #ebc600, #e3b600, #f6d500, #ffe900, #ffe90a, #edc800) content-box, linear-gradient(#f6d600, #f6d600) padding-box

    Это дает нам металлическую кнопку (пока без тени):

    Для тени добавим третий слой фона, для которого мы зададим обоим свойствам background-clip и background-origin значение border-box . Этим фоном будет неповторяющийся radial-gradient() , положение которого мы привяжем к bottom (а по горизонтали к середине) и который мы сожмем по вертикали так, что он поместится внутри нижней стороны рамки и даже еще немного места останется — пусть он будет размером, скажем, где-то .75 от значения border-width .

    radial-gradient(rgba(#787878, .9), rgba(#787878, 0) 70%) 50% bottom / 80% .75*$bw no-repeat border-box

    И всё! Можете поиграть с этими кнопками в следующем примере на CodePen:

    Для свойства background-clip наверняка найдётся множество применений! Особенно при наложении разных эффектов по краям элементов.

    P.S. Это тоже может быть интересно:
    • Тёмная сторона CSS: выходим за рамки и взрываем звезды с border-image и градиентами
    • CSS COLORS
    • CSS-выражения от контейнера для дизайнеров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *