Страницы

Поиск по вопросам

понедельник, 9 декабря 2019 г.

Артефакты прорисовки теней в рамке с уголком

#html #css


Надо мне сверстать рамку с уголком подобного вида:



Подобных вопросов и на ru so и в сети находится достаточно, чтобы на чистом css и
без картинок. Сделал по гайдлайнам что-то типа:



    .sticky {
        width: 20rem;
    }

    .sticky div {
        position:relative;
        background-color: #FFFFCC;
        padding: 1rem 2rem;
        box-shadow:0 1px 1px rgba(0,0,0,0.2), -1px 1px 1px rgba(0,0,0,0.1);
    }
    
    .sticky div:before {
        content:"";
        position:absolute;
        top:0;
        right:0;
        border-width:0 16px 16px 0;
        border-style:solid;
        border-color:#FFFF99 #fff;
        box-shadow:0 1px 1px rgba(0,0,0,0.1), -1px 1px 1px rgba(0,0,0,0.01);
    }

Some text here

Phone: 322 223

Email: test@example.tld

Я не понял, как сделать диагональную линию, но в принципе, накидав побольше теней получил вполне устраивающий результат в Firefox: Но когда я открываю это всё в Chrome я вижу какую-то уродливую тень, заметную невооружённым глазом (потом пересматривая в FF под лупой вижу, что и там она есть, но не так сильно бросается в глаза) Выключена внешняя тень, оставлена тень от уголка: Выключена тень от уголка, оставлена внешняя тень: Без теней листочек получается какой-то бедный с изобразительной точки зрения, ненастоящий, поэтому у меня возникает следующий вопрос: как кроссбраузерно сделать тень только слева и снизу и чтобы сверху и справа не было не было артефактов?


Ответы

Ответ 1



Box-shadow: blur & spread Используя свойство box-shadow, чаще всего указывают всего три параметра: смещение по X, смещение по Y и размер размытия (blur). При этом незаслуженно забывая ещё об одном параметре — spread. В разных мануалах, его называют по-разному — распространение или сжатие — скорее всего, это потому, что параметр может принимать, как положительные значения, так и отрицательные, в зависимости от задач. А также потому, что например, в Chrome этот параметр нельзя выставить меньше нуля нативным средством в инспекторе стилей (хотя, прописав значение вручную, всё прекрасно отображается и работает, если не двигать ползунок): Так что же делает этот параметр? Интерактивный пример, расставляет всё по местам: .controls{display:flex;justify-content:space-around;text-align:center}.controls input{display:block}:root{--cx:0;--cy:0;--sb:50px;--ss:0}.example{margin:15px auto;width:350px;height:70px;line-height:70px;text-align:center;box-sizing:border-box;border:4px solid #fa0;background-color:rgba(255,255,255,0);box-shadow:var(--cx) var(--cy) var(--sb) var(--ss) rgba(0,0,0,0.5)}
offset_X (-n...n)смещение по X
offset_Y (-n...n)смещение по Y
blur (0...n)размытие
spread (-n...n)распространение
rgba(0, 0, 0, 0.5) 0px 0px 50px 0px
Подведём итоги наблюдений: Смещения — могут быть, как положительными, так и отрицательными; Размытие — это не размер тени, хотя и влияет на её размер визуально. Размытие как бы смазывает границу тени. Может принимать только положительное значение; Распространение — это размер тени, относительно блока, который её отбрасывает. Может принимать, как положительные, так и отрицательные значения. Отрицательное значение не может быть меньше половины меньшего из размеров блока. Например, если height блока 70px, то при значении spread меньше -34px тень просто схлопнется (70 / 2 - 35 = 0). При этом, исчезнет и её размытие, каким бы большим оно ни было, т.к. размывать нечего. После небольшого отступления в теорию, переходим к ответу на вопрос: body { background-color: #d4ebf7; } .sticky, .sticky_right { /* Здесь добавил и изменил стили только для сниппета */ width: 18rem; float: left; margin: 3px; } /********************** * Исправленный стикер * **********************/ .sticky div { position: relative; background-color: #FFFFCC; padding: 1rem 2rem; } .sticky div:before { content: ''; position: absolute; top: 0; right: 0; z-index: 1; border-width: 0 16px 16px 0; border-style: solid; border-color: #FFFF99 #fff; box-shadow: -1px 2px 2px -1px rgba(0, 0, 0, 0.3); } .sticky div:after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 100%; z-index: -1; box-shadow: -2px 3px 3px -1px rgba(0, 0, 0, 0.3); } /******************** * Правильный стикер * ********************/ .sticky_right div { position: relative; /* Фон изменён со сплошного на градиент */ background-image: linear-gradient(225deg, transparent 10px, #FFFFCC 10px); padding: 1rem 2rem; } .sticky_right div:before { content: ''; position: absolute; top: 0; right: 0; z-index: 1; border-width: 0 16px 16px 0; border-style: solid; /* Цвет изменён с белого на прозрачный */ border-color: #FFFF99 transparent; box-shadow: -1px 2px 2px -1px rgba(0, 0, 0, 0.3); } .sticky_right div:after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 100%; z-index: -1; box-shadow: -2px 3px 3px -1px rgba(0, 0, 0, 0.3); }

Some text here

Phone: 322 223

Email: test@example.tld

Some text here

Phone: 322 223

Email: test@example.tld

Алгоритм прост, изменения минимальны: :before — в свойстве box-shadow с помощью параметра spread уменьшаем размер тени, но при этом сдвигаем тень ещё больше, в том же направлении, куда она была сдвинута ранее. Добавляем положительный z-index, на всякий случай. :after — добавляем. Выравниваем по левому и нижнему краю. Растягиваем по размерам родителя. Позиционируем с помощью отрицательного z-index за блоком. С box-shadow проводим те же манипуляции, что и с предыдущим блоком — уменьшаем тень четвёртым параметром и сдвигаем влево вниз. Таким образом, за счёт смещений, тень осталась на своём месте, но из-за отрицательного распространения, стала меньше и спряталась под основной блок на противоположных от направления смещений краях. PS Т.к. была замечена, на мой взгляд, ещё одна недоработка — непрозрачность в месте отгиба — добавил рядом ещё вариант для сравнения. Кроссбраузерность напрямую зависит от поддержки linear-gradient.

Комментариев нет:

Отправить комментарий