防止盒子阴影显示在特定一侧

发布于 2024-08-23 14:29:06 字数 1025 浏览 9 评论 0原文

有没有什么方法可以创建一个 css box-shadow,其中无论模糊值如何,阴影都只出现在所需的侧面?

例如,如果我想创建一个在左侧和右侧有阴影而在顶部或底部没有阴影的 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;}

Is there any way to create a css box-shadow in which regardless of the blur value, the shadow only appears on the desired sides?

For example if I want to create a div with shadows on left and right sides and no shadow on the top or bottom. The div is not absolutely positioned and its height is determined by the content.

-- Edit --

@ricebowl: I appreciate your answer. Maybe you can help with creating a complete solution to fix the problems stated in my reply to your solution... My page setup is as follows:

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

And CSS like this:

#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;}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

一曲琵琶半遮面シ 2024-08-30 14:29:06

您可以定义第四个距离,称为扩展偏移量,它将阴影在所有 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);

There is a fourth distance you can define called the spread offset, which moves the shadow in or out on all 4 sides. So if you set that to the negative of the blur distance, this will shift the shadow inwards by the same distance as the blur extends the shadow outwards effectively hiding it. Of course this will also shift the shadow inwards on the side you do want it to appear so you'll need to increase the offset by the blur distance to undo that. i.e.

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

So in your example:

box-shadow: -8px 0px 5px -5px rgba(0,0,0,.8), 8px 0px 5px -5px rgba(0,0,0,.8);
多情出卖 2024-08-30 14:29:06

更新

截至 2020 年,所有主要浏览器均支持 clip-path。 (参见下面的解决方案 1)。

原始答案

我有两种可能的解决方案,可以完全产生所需的效果:某些边缘上有“正常”的框阴影,而其他边缘上没有任何阴影。这个问题和其他问题中列出的许多解决方案都会导致阴影在接近没有阴影的边缘时“消散”,而我真的相信大多数人都想要一个干净的截止线。

然而,这两种解决方案都有一些警告。


解决方案 1:clip-path(实验性)

如果您愿意使用仅部分支持的实验性技术,则可以使用 clip-path 属性

在您的情况下,您将使用 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:clip(已弃用)

如果:

  1. 您愿意在相关 div 上设置 position:absolute
  2. 并且您知道div 的尺寸
  3. 或者您不知道 div 的尺寸,但您愿意
    仅删除顶部和/或左侧阴影

...您可以使用已弃用 剪辑属性

您需要使用 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);
}

上面的代码将剪掉顶部和底部的盒子阴影,同时留下 5px 左右的盒子阴影。请注意,必须知道 div 的大小。

如果 div 的大小未知,此方法将仅适用于使用 clip: rect(0, 3000px, 3000px, 0); 之类的内容来裁剪顶部和左侧阴影> (请注意右侧和底部值的巨大值,以允许 div 为任意大小)。

Update

clip-path, as of 2020, is supported in all major browsers. (See Solution 1 below).

Original Answer

I have 2 possible solutions that produce exactly the desired effect: a "normal" box shadow on some edges and nothing on other edges. Many of the solutions listed in this and other S.O. questions result in shadows that "dissipate" as they near the edge that is to have no shadow, when really I believe most people are wanting a clean cut-off.

However, both solutions come with caveats.


Solution 1: clip-path (experimental)

If you are willing to use experimental technology with only partial support, you could use the clip-path property.

In your case you would use clip-path: inset(px px px px); where the pixel values are calculated from the edge in question (see below).

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

This will clip the div in question at:

  • 0 pixels from the top
  • 5 pixels outside of the right edge (to include the shadow)
  • 0 pixels from the bottom
  • 5 pixels outside of the left edge (to include the shadow)

Note that no commas are required between pixel values.

Absolute positioning is not required and the size of the div can be flexible.


Solution 2: clip (deprecated)

If:

  1. you were willing to set position: absolute on the div in question
  2. AND you know the dimensions of the div
  3. OR you don't know the dimensions of the div but you are willing to
    only remove the top and/or left shadows

...you could use the deprecated clip property.

You'd need to use clip: rect(px, px, px, px); where the pixel values are calculated from the top left. I've used it as follows to cut off the top box-shadow but keep the bottom and sides:

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

The above will clip the top and bottom box-shadows while leaving the 5px left and right box-shadows. Note that the size of the div must be known.

If the size of the div is not known this method will only work to clip the top and left shadows using something like clip: rect(0, 3000px, 3000px, 0); (note the massive value for the right and bottom values to allow the div to be any size).

花心好男孩 2024-08-30 14:29:06

您还可以使用 Clip:rect(0px, 210px, 200px, -10px);

遗憾的是,我一直无法找到一种方法让它与灵活大小的盒子一起工作。

我经常将其用于下拉菜单,我只希望侧面和底部有阴影。在这种情况下,我只需将右侧和底部的剪辑值设置为某个较高的数字,例如

Clip: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;
}

You can also use clip:rect(0px, 210px, 200px, -10px);

Sadly I was never able to figure out a way to get it to work with a flexible sized box.

I often use this for drop down menues where I only want shadow on sides and bottom. In that case I just set the right and bottom clip values to some high number, such as

clip:rect(0px, 1000px, 1000px, -10px); /* Clip the top of the box-shadow off */

#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;
}
女中豪杰 2024-08-30 14:29:06

有,但相当脆弱。

使用以下 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。)

如果您向包含的元素添加边距(尤其是

元素,这就是我使用 padding 代替的原因)。但是,几乎可以将 -moz-box-shadow (和/或 -webkit-box-shadow)应用于 #content div ,并使用 #wrap div 来裁剪阴影,使用 overflow-y:hidden; 当然,这使得它更加脆弱,因为浏览器的数量尊重overflow-y

另一方面,解释 box-shadow 的浏览器或多或少肯定会适当地处理 overflow-y

There is, but it's fairly fragile.

Using the following 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>

And the following 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;
 }

(Live demo located here: http://davidrhysthomas.co.uk/so/shadows.html.)

The fragility creeps in if you add margins to the contained elements (especially the <p> elements, which is why I used padding instead). But, pretty much, apply the -moz-box-shadow (and/or -webkit-box-shadow) to the #content div, and use the #wrap div to clip the shadow, using overflow-y: hidden; this, of course, makes it even more fragile due to the number of browsers that respect overflow-y.

On the other hand, the browsers that interpret the box-shadow more or less certainly deal appropriately with overflow-y.

套路撩心 2024-08-30 14:29:06

执行此操作的方法是将带有阴影的框放在将溢出设置为“隐藏”的 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>

Display:

在此处输入图像描述

您可以调整#container 填充和大小以适合您的需要。在此示例中,我剪切了 #shadow-box 的底部边框。

The way to do this is to put the box with the shadow under a div that has overflow set to 'hidden'. For example, to create a shadow around a box that only appears on the left, top and right sides:

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>

Display:

enter image description here

You can adjust the #container padding and size to clip appropriate for your needs. In this example, I'm clipping the bottom border of the #shadow-box.

沒落の蓅哖 2024-08-30 14:29:06

正如我在我的一个相关问题中所说,这个问题的解决方案要么非常模糊,要么用当前的技术是不可能的。实在太糟糕了,没有办法实现这一点,因为这是网页设计中的常见主题。

我求助于使用 png 阴影,因为它似乎是唯一明智的解决方案。

感谢您的所有建议。

As I stated in a related question of mine the solution to this problem is either very obscure or is not possible with the current technology. Its really too bad there is no way of accomplishing this as it is a common theme in web design.

I resorted to using a png shadow as it seems to be the only sane solution.

Thanks for all of your suggestions.

情深如许 2024-08-30 14:29:06

如果为目标元素及其相邻元素设置 z 索引,则可以防止边缘出现阴影/模糊。在您不想要阴影/模糊的边缘,通过 z-index 属性将相邻元素放置在更高的平面上。例如,如果您的侧面导航带有盒阴影“box-shadow:6px 0px 10px #bdbdbd”,则box-shadow属性将导致顶部边缘(标题上)出现一些出血。您可以通过为标题上的 z-index 属性设置比 nav 元素的 z-index 更高的值来防止 box-shadow 属性的模糊渗入到标题元素上。您需要将 header 和 nav 元素的位置设置为“relative”,否则 z-index 将不起作用(z-index 不适用于默认位置“static”)。

我为标题的 z 索引随机选择值 10,为导航元素的 z 索引随机选择值 9。这会将标题放置在导航元素的顶部,并且您不会在该边缘看到阴影/模糊。

#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;
}

You can prevent a shadow/blur on an edge if you set the z-index for the target element and it's neighboring element. On the edge that you don't want a shadow/blur, place the neighboring element on a higher plane through the z-index property. For example, if you have a side navigation with a box shadow "box-shadow: 6px 0px 10px #bdbdbd", the box-shadow property will cause some bleeding on the top edge (onto the header). You can prevent the blur from the box-shadow property to bleed onto the header element by setting a higher value for the z-index property on the header than the z-index for the nav element. You will need to set the position for both the header and nav elements to "relative" otherwise the z-index will not work (z-index does not work with the default position "static").

I randomly selected the value 10 for the header's z-index and 9 for the nav element's z-index. This places the header on top of the nav element and you will not see a shadow/blur on that edge.

#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;
}
妳是的陽光 2024-08-30 14:29:06

我认为相邻边总是可能会有一点渗透,随着模糊值的增加,这种渗透会变得更加明显。您可以通过在希望出现阴影的一侧使用较低的模糊度和较高的偏移量来抵消感知到的渗透。例如,这会在侧面产生明显的阴影,在顶部和底部产生几乎看不见的阴影:

box-shadow: #888 3px 0px 2px, #888 -3px 0px 2px;

I think there is always likely to be a little bleed-through to adjacent sides that will become more obvious with higher blur values. You can offset the perceived bleed-through by using a low blur and a higher offset on the sides you want the shadow to appear on. For example, this would create a noticeable shadow on the sides and a nearly invisible one on the top and bottom:

box-shadow: #888 3px 0px 2px, #888 -3px 0px 2px;
自由范儿 2024-08-30 14:29:06

基于 Michaels 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>

浏览器对剪辑路径的支持相当不错。这是一个很好的用于创建剪辑路径蒙版的小工具

Michaels spread-offset based solution is pretty good. Problem with that is that the box shadow doesn't run to the edge which probably is exactly what most people want the shadow to look like.

Below is my clip-path based approach wich not only let you cut the shadow hard but also allows for better control on which sides the shadow should appear. Here a comparison between normal, spread-offset and 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>

Browser support for clip path is pretty decent. Here is a nice little tool for creating clip-path masks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文