使用纯CSS实现图片悬停时的黑色透明覆盖层?

115

我想通过CSS来实现鼠标悬停在图像上时添加一个透明黑色叠加层。这可行吗?我尝试了下面的代码:

http://jsfiddle.net/Zf5am/565/

但我无法让叠加层出现。

<div class="image">
    <img src="http://www.newyorker.com/online/blogs/photobooth/NASAEarth-01.jpg" alt="" />
    <div class="overlay" />
</div> 

.image {
  position: relative;
  border: 1px solid black;
  width: 200px;
  height: 200px;
}
.image img {
  max-width: 100%;
  max-height: 100%;
}
.overlay {
  position: absolute;
  top: 0;
  left: 0;
  display: none;
  background-color: red;
  z-index: 200;
}
.overlay:hover {
  display: block;
}

你是不是想在图片 div 上加上 :hover,而不是覆盖层 div? - andi
1
只是一点提示:为什么要在覆盖层上设置如此高的Z-index值?Z-index不是全局的;没有必要通过设置高或低的值来“破解”它们的工作方式。 - Jimmy Breck-McKye
1
这是最终帮助我解决问题的方法:http://jsfiddle.net/4Dfpm/ 不需要覆盖层div。鼠标悬停时图像透明度降低,下面的div应该有黑色背景,完成。 - Avatar
8个回答

241

我建议使用伪元素替换遮罩层元素。因为伪元素不能添加到包含的 img 元素上,所以您仍需要将 img 元素包装起来。

此处是实时示例 -- 此处是带文本的示例

<div class="image">
    <img src="http://i.stack.imgur.com/Sjsbh.jpg" alt="" />
</div>

关于CSS,需要在.image元素上设置可选的尺寸,并将其相对定位。如果你想要一个响应式图片,只需省略尺寸即可,这仍然有效(示例)。值得注意的是,尺寸必须在父元素上而不是img元素本身中设置,请参见

.image {
    position: relative;
    width: 400px;
    height: 400px;
}

给子元素img设置宽度100%,并添加vertical-align:top以解决默认对齐问题。

.image img {
    width: 100%;
    vertical-align: top;
}

伪元素方面,设置一个内容值并将其绝对定位相对于.image元素。宽度/高度为100%将确保此功能与不同的img尺寸一起使用。如果想要过渡元素,请设置0的不透明度并添加过渡属性/值。

.image:after {
    content: '\A';
    position: absolute;
    width: 100%; height:100%;
    top:0; left:0;
    background:rgba(0,0,0,0.6);
    opacity: 0;
    transition: all 1s;
    -webkit-transition: all 1s;
}

当悬停在伪元素上时,使用不透明度1以促进过渡效果:

.image:hover:after {
    opacity: 1;
}

在这里查看最终结果


如果您想要在悬停时添加文本:

对于最简单的方法,只需将文本作为伪元素的content值添加即可:

在这里查看示例

.image:after {
    content: 'Here is some text..';
    color: #fff;

    /* Other styling.. */
}

那在大多数情况下应该有效;但是,如果您有不止一个img元素,则可能不希望相同的文本在悬停时出现。因此,您可以将文本设置在data-*属性中,从而为每个img元素设置唯一的文本。

这里有示例

.image:after {
    content: attr(data-content);
    color: #fff;
}

使用attr(data-content)作为content属性的值,伪元素将会添加来自具有data-content属性的.image元素的文本内容:

<div data-content="Text added on hover" class="image">
    <img src="http://i.stack.imgur.com/Sjsbh.jpg" alt="" />
</div>

你可以添加一些样式,并像这样做:

这里有个例子

在上面的示例中,:after 伪元素用作黑色遮罩层,而 :before 伪元素则是标题/文本。由于这些元素是相互独立的,因此您可以使用单独的样式来获得更优化的定位。

.image:after, .image:before {
    position: absolute;
    opacity: 0;
    transition: all 0.5s;
    -webkit-transition: all 0.5s;
}
.image:after {
    content: '\A';
    width: 100%; height:100%;
    top: 0; left:0;
    background:rgba(0,0,0,0.6);
}
.image:before {
    content: attr(data-content);
    width: 100%;
    color: #fff;
    z-index: 1;
    bottom: 0;
    padding: 4px 10px;
    text-align: center;
    background: #f00;
    box-sizing: border-box;
    -moz-box-sizing:border-box;
}
.image:hover:after, .image:hover:before {
    opacity: 1;
}

1
谢谢Josh。我最喜欢这个版本。如果您想在透明的黑色背景上显示一些白色文本,您会怎么做?您会添加另一个div并单独应用不透明度吗? - RobVious
是的,只有在悬停时才会触发。 - RobVious
1
谢谢,这是比我之前尝试过的更好的解决方案。 - wingskush
1
我该如何将标题设置为图像的中心?top:30%可以工作,请参见我的fiddle,但对于响应式布局,将其设置为确切的中心会更好。顺便说一句:感谢您提供这个好答案。 - p2or
3
@poor 这是一种响应式的方法(更新的示例),它使用top: 50%/transform: translateY(-50%)来实现垂直居中。这是我在另一个答案中提到的方法之一,参见https://dev59.com/J2025IYBdhLWcg3w9quQ#25799339。 - Josh Crozier
显示剩余2条评论

60

1
自从FF35发布以来,FF也支持过滤器:http://jsfiddle.net/Zf5am/1766/. - Jacob van Lingen
哥们儿!太棒了!解决方案真是太赞了! - Alvaro Silvino
这有多简单! - Sixteen
需要注意的是,根据此页面 https://caniuse.com/?search=-webkit-filter ,现在大多数浏览器都支持filter - MQuiggGeorgia

12

你很接近了。这个可以用:

.image { position: relative; border: 1px solid black; width: 200px; height: 200px; }
.image img { max-width: 100%; max-height: 100%; }
.overlay { position: absolute; top: 0; left: 0; right:0; bottom:0; display: none; background-color: rgba(0,0,0,0.5); }
.image:hover .overlay { display: block; }

你需要在图片上添加 :hover,并通过添加 right:0;bottom:0; 使 .overlay 覆盖整个图片。

jsfiddle链接: http://jsfiddle.net/Zf5am/569/


我还建议使用CSS3动画来实现兼容浏览器的平滑过渡(IE用户只能忍受)。 - Jimmy Breck-McKye

7

在图片的div上使用:before和:after是一个很好的方法,而不是额外添加覆盖层的方法。以下是示例代码:http://jsfiddle.net/Zf5am/576/

<div class="image">
    <img src="http://www.newyorker.com/online/blogs/photobooth/NASAEarth-01.jpg" alt="" />
</div>

.image {position:relative; border:1px solid black; width:200px; height:200px;}
.image img {max-width:100%; max-height:100%;}
.image:hover:after {content:""; position:absolute; top:0; left:0; bottom:0; right:0; background-color: rgba(0,0,0,0.3);}

2

.overlay没有高度或宽度,也没有内容,你无法悬停在display:none上。

我改为将该div与.image具有相同的大小和位置,并在悬停时更改了RGBA值。

http://jsfiddle.net/Zf5am/566/

.image { position: absolute; border: 1px solid black; width: 200px; height: 200px; z-index:1;}
.image img { max-width: 100%; max-height: 100%; }
.overlay { position: absolute; top: 0; left: 0; background:rgba(255,0,0,0); z-index: 200; width:200px; height:200px; }
.overlay:hover { background:rgba(255,0,0,.7); }

1

看看我在这里做了什么:http://jsfiddle.net/dyarbrough93/c8wEC/

首先,您从未设置覆盖层的尺寸,这意味着它一开始就不会显示。其次,我建议当您悬停在图像上时只更改覆盖层的z-index。根据您的需求更改覆盖层的不透明度/颜色。

.image { position: relative; width: 200px; height: 200px;}
.image img { max-width: 100%; max-height: 100%; }
.overlay { position: absolute; top: 0; left: 0; background-color: gray; z-index: -10; width: 200px; height: 200px; opacity: 0.5}
.image:hover .overlay { z-index: 10}

1
你可以通过调整图像的透明度并将图像的背景颜色设置为黑色来实现这一点。通过使图像变得透明,它会显得更暗。
<div class="image">
    <img src="http://www.newyorker.com/online/blogs/photobooth/NASAEarth-01.jpg" alt="" />
</div> 

CSS:
.image { position: relative; border: 1px solid black; width: 200px; height: 200px; background: black; }
.image img { max-width: 100%; max-height: 100%; }
.image img:hover { opacity: .5 }

你可能还需要设置浏览器特定的不透明度,以使其在其他浏览器中也能正常工作。


0

我会给你的覆盖层div设置一个最小高度和最小宽度,大小与图片相同,并在悬停时更改背景颜色

.overlay { position: absolute; top: 0; left: 0;  z-index: 200; min-height:200px; min-width:200px; background-color: none;}
.overlay:hover { background-color: red;}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接