Запретить отображение тени блока на определенной стороне

Есть ли способ создать тень окна css, в которой независимо от значения размытия тень появляется только с желаемых сторон?

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

-- Редактировать --

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

<div id="container">
    <div id="header"></div>
    <div id="content"></div>
    <div id="clearfooter"></div>
</div>
<div id="footer"></div>

И CSS вот так:

#container {width:960px; min-height:100%; margin:0px auto -32px auto; 
       position:relative; padding:0px; background-color:#e6e6e6; 
       -moz-box-shadow: -3px 0px 5px rgba(0,0,0,.8), 
       3px 0px 5px rgba(0,0,0,.8);}
#header   {height:106px; position:relative;}
#content   {position:relative;}
#clearFooter {height:32px; clear:both; display:block; padding:0px; margin:0px;}
#footer  {height:32px; padding:0px; position:relative; width:960px; margin:0px 
           auto 0px auto;}

person Jason Turner    schedule 02.03.2010    source источник


Ответы (9)


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

box-shadow: (horizontal + blur) 0px (blur) (-blur) color;

Итак, в вашем примере:

box-shadow: -8px 0px 5px -5px rgba(0,0,0,.8), 8px 0px 5px -5px rgba(0,0,0,.8);
person Michael    schedule 02.05.2011
comment
Отличное решение распространенной проблемы! - person maxedison; 26.05.2016

У меня есть 2 возможных решения, которые производят в точности желаемый эффект: «нормальная» тень блока на некоторых краях и ничего на других краях. Многие из решений, перечисленных в этом и других S.O. Вопросы приводят к появлению теней, которые «рассеиваются» по мере приближения к краю, который не должен иметь тени, тогда как я действительно считаю, что большинство людей хотят четкого отсечения.

Однако оба решения имеют оговорки.


Решение 1. clip-path (экспериментальное)

Если вы хотите использовать экспериментальную технологию с частичной поддержкой, вы можете использовать _ 1_ свойство.

В вашем случае вы должны использовать clip-path: inset(px px px px);, где значения пикселей рассчитываются от рассматриваемого края (см. Ниже).

#container {
    box-shadow: 0 0 5px rgba(0,0,0,0.8);
    clip-path: inset(0px -5px 0px -5px);
}

Это приведет к обрезанию рассматриваемого div по адресу:

  • 0 пикселей сверху
  • 5 пикселей за правым краем (чтобы включить тень)
  • 0 пикселей снизу
  • 5 пикселей за пределами левого края (чтобы включить тень)

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

Абсолютное позиционирование не требуется, и размер div может быть гибким.


Решение 2: зажим (не рекомендуется)

Если:

  1. вы хотели установить position: absolute для рассматриваемого div
  2. И вы знаете размеры div
  3. ИЛИ вы не знаете размеры div, но хотите удалить только верхнюю и / или левую тени

... вы можете использовать устаревшее свойство clip.

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

#container {
    position: absolute;
    box-shadow: 0 0 5px rgba(0,0,0,0.8);
    width: 100px;
    height: 100px;
    clip: rect(0px, 105px, 100px, -5px);
}

Вышеупомянутое будет обрезать верхнюю и нижнюю тени блока, оставляя 5 пикселей левой и правой тени блока. Обратите внимание, что размер div должен быть известен.

Если размер div неизвестен, этот метод будет работать только для обрезки верхней и левой тени, используя что-то вроде clip: rect(0, 3000px, 3000px, 0); (обратите внимание на большое значение для правого и нижнего значений, чтобы div мог быть любым размер).

person Luke    schedule 15.12.2016

Вы также можете использовать clip: rect (0px, 210px, 200px, -10px);

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

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

клип: rect (0px, 1000px, 1000px, -10px); / * Отрезаем верхнюю часть тени блока * /

#box{
    box-shadow:             0px 0px 10px rgba(0, 0, 0, 0.7);
    -moz-box-shadow:     0px 0px 10px rgba(0, 0, 0, 0.7);
    -webkit-box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.7);
    clip:rect(0px, 210px, 200px, -10px); /* Clip the top and bottom of the box-shadow off */
    width:200px;
    height: 200px;
    position: absolute;
    top:50px;
    left:50px;
    background:#eee;
}
person Alex    schedule 28.05.2011
comment
+1, лучшее решение в моем случае (узнав, что clip требует position:absolute!) - person schellmax; 04.04.2013
comment
Это отлично сработало для меня. Используется для создания тени в псевдоэлементе: before. Хотел бы я проголосовать еще пару раз = P - person shousper; 24.05.2013
comment
RE: 2016 Clip - устаревший класс, требующий известной ширины / высоты и странный в том, что он форматирует все размеры позиций, начинающиеся с 0,0. Но он все еще имеет достаточно широкую поддержку, в то время как новый -webkit-clip-path все еще плохо реализован. - person mix3d; 26.04.2016

Есть, но довольно хрупкий.

Используя следующий xhtml:

<div id="wrap">

 <div id="content">

   <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales justo nec mauris aliquam vitae feugiat magna congue. Morbi dignissim volutpat dui id porttitor. Donec auctor feugiat dolor, at varius magna rhoncus sed. Vivamus a odio urna, iaculis dignissim lectus. Integer aliquam felis eu sapien vestibulum ornare. Vivamus nec euismod sapien. Mauris quis eros ligula, sed pulvinar sem. Aenean sodales tempor malesuada. Aliquam erat volutpat. Aenean vel eros velit, et porttitor elit. Phasellus volutpat blandit quam eu fringilla. Integer ornare convallis tincidunt. Suspendisse commodo iaculis est vulputate volutpat. Donec at massa arcu. Sed sit amet commodo mauris. Aliquam erat volutpat. Integer eu augue vel erat euismod volutpat eu vel massa. Curabitur id erat vitae nisi imperdiet scelerisque id ut arcu. Quisque commodo dolor vitae erat imperdiet consectetur.</p>

   <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sodales justo nec mauris aliquam vitae feugiat magna congue. Morbi dignissim volutpat dui id porttitor. Donec auctor feugiat dolor, at varius magna rhoncus sed. Vivamus a odio urna, iaculis dignissim lectus. Integer aliquam felis eu sapien vestibulum ornare. Vivamus nec euismod sapien. Mauris quis eros ligula, sed pulvinar sem. Aenean sodales tempor malesuada. Aliquam erat volutpat. Aenean vel eros velit, et porttitor elit. Phasellus volutpat blandit quam eu fringilla. Integer ornare convallis tincidunt. Suspendisse commodo iaculis est vulputate volutpat. Donec at massa arcu. Sed sit amet commodo mauris. Aliquam erat volutpat. Integer eu augue vel erat euismod volutpat eu vel massa. Curabitur id erat vitae nisi imperdiet scelerisque id ut arcu. Quisque commodo dolor vitae erat imperdiet consectetur.</p>

 </div>

</div>

И следующий css:

#wrap {width: 70%;
 margin: 1em auto;
 overflow: hidden;
 overflow-x: visible;
 }

#content
 {width: 90%;
 margin: 0 auto;
 -moz-box-shadow: 0 0 1em #ccc;
 -webkit-box-shadow: 0 0 1em #ccc;
 }

#content p
 {overflow-y: hidden;
 padding: 0.5em 0;
 }

(Живая демонстрация находится здесь: http://davidrhysthomas.co.uk/so/shadows.html.)

Хрупкость закрадывается, если вы добавляете поля к содержащимся элементам (особенно элементам <p>, поэтому я использовал вместо этого padding). Но, в значительной степени, примените -moz-box-shadow (и / или -webkit-box-shadow) к #content div и используйте #wrap div для обрезки тени, используя overflow-y: hidden;, это, конечно, сделает его еще более хрупким из-за количества браузеров, которые уважают overflow-y .

С другой стороны, браузеры, которые интерпретируют box-shadow, более или менее определенно правильно работают с overflow-y.

person David says reinstate Monica    schedule 02.03.2010
comment
Спасибо @Jimmy Cuadra, отредактировано, чтобы исправить мою опечатку. Должно работать сейчас =) - person David says reinstate Monica; 02.03.2010
comment
Хм, в какой-то степени это работает. Однако мне нужно, чтобы он работал в решении, где div с тенями является основным div содержимого и имеет высоту 100%, даже если содержимое не заполняет это пространство. Я могу заставить его работать, когда контент больше, чем окно браузера, или когда меньше по отдельности, но никогда в обоих случаях. Спасибо за вашу помощь, рисовая чаша, думаю, мне придется вернуться к тени изображения. : \ Вот и все о css3. - person Jason Turner; 02.03.2010

Чтобы сделать это, поместите прямоугольник с тенью под div, для которого установлено значение «скрыто» для переполнения. Например, чтобы создать тень вокруг прямоугольника, которая появляется только слева, сверху и справа:

CSS:

#container {
    height: 101px;
    overflow: hidden;
    padding: 5px 5px 0;
    width: 105px;
}
#shadow-box {
   border:1px solid #aaa;
   width:100px;
   height:100px;
   box-shadow:0 0 4px 1px #666;
}

HTML:

<div id="container">
   <div id="shadow-box"></div>
<div>

Отображать:

введите описание изображения здесь

Вы можете настроить заполнение и размер контейнера #container в соответствии с вашими потребностями. В этом примере я обрезаю нижнюю границу # shadow-box.

person Redtopia    schedule 21.10.2012
comment
Было бы лучше использовать псевдоэлемент, например #container :: after, если вы собираетесь это сделать. - person Senthe; 18.01.2017

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

Я прибег к использованию тени png, так как это кажется единственным разумным решением.

Спасибо за все ваши предложения.

person Jason Turner    schedule 13.05.2010
comment
См. stackoverflow.com / questions / 2359578 / за ответ. - person Jason Turner; 14.12.2011

Вы можете предотвратить появление тени / размытия на краю, если вы установите z-index для целевого элемента и его соседнего элемента. На краю, на котором вам не нужна тень / размытие, поместите соседний элемент на более высокую плоскость с помощью свойства z-index. Например, если у вас есть боковая навигация с тенью блока box-shadow: 6px 0px 10px #bdbdbd, свойство box-shadow вызовет некоторое кровотечение на верхнем крае (в заголовке). Вы можете предотвратить растекание размытия от свойства box-shadow на элемент заголовка, установив более высокое значение для свойства z-index в заголовке, чем z-index для элемента nav. Вам нужно будет установить относительную позицию для элементов заголовка и nav, иначе z-index не будет работать (z-index не работает со статической позицией по умолчанию).

Я случайным образом выбрал значение 10 для z-индекса заголовка и 9 для z-индекса навигационного элемента. Это помещает заголовок поверх навигационного элемента, и вы не увидите тени / размытия на этом краю.

#header {
    background-color: #1c2a48;
    display: flex;
    position: relative;
    z-index: 10;
    width: 100%;
}
#nav {
    display: flex;
    float: left;
    position: relative;
    z-index: 9;
    height: calc(100vh - 44.6px) !important;
    width: 187px;
    border-right: .5px solid rgba(180,180,180,0.7);
    background-color: #fafafa;
    box-shadow: 6px 0px 10px #bdbdbd;
}
person Jay Jara    schedule 28.07.2020

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

box-shadow: #888 3px 0px 2px, #888 -3px 0px 2px;
person Jimmy    schedule 02.03.2010
comment
Почти невидимый в этом случае не годится, так как почти невидимые тени вызывают полосы прокрутки. - person Jason Turner; 02.03.2010

Основанное на Майклсе spread-offset решение довольно хорошее. Проблема в том, что тень блока не достигает края, что, вероятно, является именно тем, как большинство людей хотят, чтобы тень выглядела.

Ниже представлен мой подход, основанный на clip-path, который не только позволяет сильно вырезать тень, но также позволяет лучше контролировать, с каких сторон тень должна появляться. Вот сравнение между нормальным, смещением по спреду и траекторией отсечения:

.container {
  padding: 65px 0px;
  text-align: center;
}

.box {
  display: inline-block;
  width: 50px;
  height: 50px;
  text-align: center;
  line-height: 50px;
  background: #0f0;
  margin: 15px;
}

/* default box shadow */
.box1 { 
  box-shadow: 0px 0px 10px 5px #000;
}

/* single side with spread-offset */
.box2 {
  box-shadow: 0px 10px 5px -5px rgba(0,0,0,.8);
}

/* single side with clip-path */
.box3 {
  box-shadow: 0px 0px 10px 5px #000;
  clip-path: polygon(0 0, 100% 0, 100% 300%, 0 300%);
}
    <div class="container">

      <div class="box box1">1</div>
      
      <div class="box box2">2</div>
      
      <div class="box box3">3</div>

    </div>

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

person GDY    schedule 05.01.2021