【问题标题】:Pseudo-element Background Reveal on :hover:hover 上的伪元素背景显示
【发布时间】:2017-05-05 07:31:47
【问题描述】:

总结

  • 目标设备(设备宽度+600px - 请忽略 移动/xs 屏幕
  • 纯 CSS 图片显示:hover:after
  • 有效但不理想
  • 问题
    • 图像比例(图像将为 800px/600px) 未保持 - 宽度被裁剪而不是图像被缩小
    • 图像在主容器之外.outercontainer
    • :hover 上的图像淡入 有效,但在:hover 状态为 后它确实淡出终止我尝试使用单独的动画/相同的动画倒退没有运气

想要的效果

  • 所有东西都装在带有蓝色边框的容器中 .outercontainer

  • 编辑:图像应该有自己的空间 - 大约 80% 的容器 宽度和选项/菜单将是另外 20% - 没有重叠 (如果图像重叠在选项上,平板电脑用户将陷入:悬停状态)

  • .outercontainer 里面的一切都根据屏幕调整 宽度

  • 希望支持的最小设备宽度为 600 像素(忽略小于 600 像素的屏幕)

  • 步骤:

    • 图像淡入:hover
    • 只要元素仍在:hover 中,图像就保持可见
    • 元素“未悬停”后图像淡出

类似的帖子/问题

SO 上还有更多类似的问题。我还没有找到一个解决图像作为 :after 伪元素背景的图像


我的问题

  1. 如何将 :hover:after 显示的图像放入其父容器中? (我希望它占用不超过该容器宽度的 80%-85% - 其余空间应分配给选项/菜单/列表项)

  2. 如何使用 :hover:after responsive 显示图像?

  3. 如何让元素在取消悬停后淡出?

我的CSSHTML在下面的sn-p中(不完全响应-请全屏打开)

/* Start Miscellaneous stuff */

body {
	background: #131418;
	color: #999;
	text-align: center;
}

.optionlist a {
	color: #999;
	text-decoration: none;
}

@keyframes mycoolfade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

/* End Miscellaneous stuff */

.outercontainer {
	border: 1px solid blue; /*This needs to be in the middle of the screen and everthing should fit inside it*/
	position: fixed; /*border to highlight only - not part of final product*/
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 1200px;
	max-width: 80%
}

.optioncontainer {
	width: 250px;
	max-width: 20vw;
}

.optionlist li {
	background: #fff;
	padding: .5em;
	box-shadow: inset 10px 10px 100px 25px rgba(0, 0, 0, .8);
	list-style-type: none;
}

.optionlist li:nth-child(odd) {
	background: #000;
}

.optionlist li:hover {
	background: red;
}

.optionlist li:hover:after { /* The part the needs to be fixed */
	content: '';
	width: 800px;
	height: 600px;
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	animation: mycoolfade 1s;
}

/* Start Background Control */

#red:after {background: url(http://lorempixel.com/800/600/)}

#blue:after {background: url(http://lorempixel.com/800/601/)}

#green:after {background: url(http://lorempixel.com/801/600/)}

#yellow:after {background: url(http://lorempixel.com/801/601/)}

#orange:after {background: url(http://lorempixel.com/799/600/)}

#white:after {background: url(http://lorempixel.com/800/599/)}

#black:after {background: url(http://lorempixel.com/801/599/)}

/* End Background Control */
<body>
	The initial hiccup when the images load is not an issue 
	<div class="outercontainer">
		<div class="optioncontainer">
			<div class="optionlist">
				<li id="red">Red</li>
				<li id="blue">Blue</li>
				<li id="green">Green</li>
				<li id="yellow">Yellow</li>
				<li id="orange">Orange</li>
				<li id="white">White</li>
				<li id="black">Black</li>
			</div>
		</div>
	</div>
</body>

编辑: 这是整个设置理想状态的图像。

谢谢。

【问题讨论】:

  • 赞成以完美而详细的方式提出关于 SO 的问题
  • 关注这个问题!

标签: html css


【解决方案1】:

只需将您的outercontainer 设置在您想要的任何位置。在将 outercontainer position 样式更改为 relativeafter 伪元素样式更改为 position: absolute; left: 0; top: 0; width: 100%; height: 100%; 后,似乎可以正常工作。使用 CSS 动画,您可以应用淡入淡出效果。

============ 最新变化==============

outercontainer 添加了与位置和边距相关的样式以将其显示到中心,添加了伪元素background 样式,如no-repeatbackground-size: cover。将div 标记更改为ulflex 样式为ul

/* Start Miscellaneous stuff */

body {
	background: #131418;
	color: #999;
	text-align: center;
}

.optionlist a {
	color: #999;
	text-decoration: none;
}

@keyframes mycoolfade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

/* End Miscellaneous stuff */

.outercontainer {
	border: 1px solid blue; /*This needs to be in the middle of the screen and everthing should fit inside it*/
	position: absolute; /*border to highlight only - not part of final product*/
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    min-width: 50%;
    min-height: 50%;
    width: 80%;
    height: 80%;
	transform: translate(-50%, -50%);
}

.optioncontainer {
	width: 250px;
	max-width: 20vw;
    height: 100%;
}

.optionlist {
	padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    height: 100%;
}

.optionlist li {
	background: #fff;
	padding: .5em;
	box-shadow: inset 10px 10px 100px 25px rgba(0, 0, 0, .8);
	list-style-type: none;
}

.optionlist li:nth-child(odd) {
	background: #000;
}

.optionlist li:hover {
	background: red;
}

.optionlist li:hover:after { /* The part the needs to be fixed */
	content: '';
	width: 100%;
	height: 100%;
	position: absolute;
	top: 0;
	left: 0;
	transform: translate(-50%, -50%);
	animation: mycoolfade 1s;
    z-index:-1;
}

/* Start Background Control */

#red:after {
    background: url(http://lorempixel.com/800/600/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#blue:after {
    background: url(http://lorempixel.com/800/601/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#green:after {
    background: url(http://lorempixel.com/801/600/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#yellow:after {
    background: url(http://lorempixel.com/801/601/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#orange:after {
    background: url(http://lorempixel.com/799/600/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#white:after {
    background: url(http://lorempixel.com/800/599/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

#black:after {
    background: url(http://lorempixel.com/801/599/)  no-repeat center center fixed; 
    -webkit-background-size: cover;
    -moz-background-size: cover;
    -o-background-size: cover;
    background-size: cover;
}

/* End Background Control */
<body>
	The initial hiccup when the images load is not an issue 
	<div class="outercontainer">
		<div class="optioncontainer">
			<ul class="optionlist">
				<li id="red">Red</li>
				<li id="blue">Blue</li>
				<li id="green">Green</li>
				<li id="yellow">Yellow</li>
				<li id="orange">Orange</li>
				<li id="white">White</li>
				<li id="black">Black</li>
			</ul>
		</div>
	</div>
</body>

【讨论】:

  • 非常感谢您的回答。我已经在 Chrome、FF 和 IE 上尝试过,但对它们都不起作用。主容器卡在页面顶部,图像未全尺寸显示。
  • 只需在此处运行代码 sn-p 并告诉我您的期望究竟是什么?现在悬停在outercontainer内可见的伪元素的图像。
  • 是的,我在不同的浏览器上运行它,图像没有以全尺寸显示,它们水平重复并且 .outercontainer 不在屏幕中间。它固定在页面顶部。
  • 好的,所以你想要外部容器在中心,而伪元素背景图像在里面吗?
  • 正确的 .outercontainer 进入屏幕中间。其他一切都适合它。如果它能响应屏幕尺寸,那就太好了。感谢您的宝贵时间。
【解决方案2】:

这是我的尝试

可能我遗漏了什么,如果是这种情况,请告诉我

诀窍是让 optionlist 元素的宽度始终为容器宽度的 20%。

这样,我们可以让伪元素占其父元素的 400%,这相当于容器剩余的 80% 减去选项列表。

为了处理淡出,我们需要让伪影一直存在(不仅仅是在悬停时)。因此,我们将它们声明为不透明度为 0 的基本状态,并在悬停时将其更改为不透明度 1。

这会导致您检测到的错误,因为即使不透明度为 0,悬停在伪触发器上也会触发,然后冒泡到元素。这可以通过指针事件来解决:伪上没有。

body, html {
  height: 100%;  
}

body {
  background: #131418;
  color: #999;
  text-align: center;
}
.optionlist a {
  color: #999;
  text-decoration: none;
}
/* End Miscellaneous stuff */

.outercontainer {
  border: 1px solid blue;
  /*This needs to be in the middle of the screen t*/
  position: relative;
  /*border to highlight only - not part of final product*/
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 1200px;
  max-width: 80%;
}
.optioncontainer {
  width: 20%;
}
.optionlist {
  position: relative;
  width: 100%;
}
.optionlist li {
  background: #fff;
  padding: .5em;
  box-shadow: inset 10px 10px 100px 25px rgba(0, 0, 0, .8);
  list-style-type: none;
}
.optionlist li:nth-child(odd) {
  background: #000;
}
.optionlist li:hover {
  background: red;
}
.optionlist li:after {
  content: '';
  width: 400%;
  height: 100%;
  position: absolute;
  top: 0px;
  left: 100%;
   /*background-size: cover;   */
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transition: opacity 1s;
  pointer-events: none;   /* do not trigger a hover */
}
.optionlist li:hover:after {
  opacity: 1;
}
/* Start Background Control */

#red:after {
  background-image: url(http://lorempixel.com/800/600/)
}
#blue:after {
  background-image: url(http://lorempixel.com/800/601/)
}
#green:after {
  background-image: url(http://lorempixel.com/801/600/)
}
#yellow:after {
  background-image: url(http://lorempixel.com/801/601/)
}
#orange:after {
  background-image: url(http://lorempixel.com/799/600/)
}
#white:after {
  background-image: url(http://lorempixel.com/800/599/)
}
#black:after {
  background-image: url(http://lorempixel.com/801/599/)
}
<div class="outercontainer">
  <div class="optioncontainer">
    <div class="optionlist">
      <li id="red">Red</li>
      <li id="blue">Blue</li>
      <li id="green">Green</li>
      <li id="yellow">Yellow</li>
      <li id="orange">Orange</li>
      <li id="white">White</li>
      <li id="black">Black</li>
    </div>
  </div>
</div>

【讨论】:

  • 非常感谢瓦尔!你确实设法让图像显示在我非常喜欢的盒子里!图像是否可以在不缩放的情况下以原始纵横比显示? ? 800 像素/600 像素。请检查我添加到问题中的图片。
  • 我已经移除了背景尺寸:封面,并添加了背景位置以使图像居中 现在,不会有任何图像缩放。是这个主意吗?
  • 伟大的工作瓦尔!我喜欢它,我认为它可以作为答案。只有一个小错误发生。如果您 :hover 在图像显示的位置为空时,则会显示最后一个选项的图像。如果您将光标悬停在任何可见的图像上,它也会显示出来。如果你能解决这个错误,我会选择这个作为答案 - 你也可以添加几行来解释它是如何工作的,但这完全是可选的。
  • 完成!很高兴你喜欢它!
  • 太棒了。非常感谢您的时间,并感谢您的解释。事实证明这比我预期的要好得多!我选择了这个答案,因为它是问题的完整答案。我唯一改变的是将选项列表项的填充增加到 1em。除此之外,完美!
【解决方案3】:

问题的淡入/淡出部分:

/* Start Miscellaneous stuff */

body {
	background: #131418;
	color: #999;
	text-align: center;
}

.optionlist a {
	color: #999;
	text-decoration: none;
}

/* End Miscellaneous stuff */

.outercontainer {
	border: 1px solid blue; /*This needs to be in the middle of the screen and everthing should fit inside it*/
	position: fixed; /*border to highlight only - not part of final product*/
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: 1200px;
	max-width: 80%
}

.optioncontainer {
	width: 250px;
	max-width: 20vw;
}

.optionlist li {
	background: #fff;
	padding: .5em;
	box-shadow: inset 10px 10px 100px 25px rgba(0, 0, 0, .8);
	list-style-type: none;
}

.optionlist li:nth-child(odd) {
	background: #000;
}

.optionlist li:hover {
	background: red;
}

.optionlist li:after {
    content: '';
	width: 800px;
	height: 600px;
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
    transition: opacity 1s;
    opacity: 0;
    pointer-events: none;
}

.optionlist li:hover:after {
	opacity: 1;
    pointer-events: auto;
}

/* Start Background Control */

#red:after {background: url(http://lorempixel.com/800/600/)}

#blue:after {background: url(http://lorempixel.com/800/601/)}

#green:after {background: url(http://lorempixel.com/801/600/)}

#yellow:after {background: url(http://lorempixel.com/801/601/)}

#orange:after {background: url(http://lorempixel.com/799/600/)}

#white:after {background: url(http://lorempixel.com/800/599/)}

#black:after {background: url(http://lorempixel.com/801/599/)}

/* End Background Control */
<body>
	The initial hiccup when the images load is not an issue 
	<div class="outercontainer">
		<div class="optioncontainer">
			<div class="optionlist">
				<li id="red">Red</li>
				<li id="blue">Blue</li>
				<li id="green">Green</li>
				<li id="yellow">Yellow</li>
				<li id="orange">Orange</li>
				<li id="white">White</li>
				<li id="black">Black</li>
			</div>
		</div>
	</div>
</body>

【讨论】:

  • 这正是我的想法!我记下了您是如何做到的(并且您是第一个实施这种方法的人) 想尝试解决剩下的难题吗?我不能分红,但这个答案绝对值得一提。
【解决方案4】:

好问题。我可以通过为您的.outercontainer 使用vhvw 单位并稍微更改样式来实现这一点。即将样式从:hover::after移动到::after

.optionlist li:hover::after {
  /* Just toggling visibility and setting animation here */
  animation: mycoolfadein 1s;
  display: block;
}


/* Start Background Control -changed style names for testing */

.listitem::after {
  content: "";
  width: 80vw;
  height: 70vh;
  background-image: url(http://lorempixel.com/800/600/);
  background-size: 80vw 70vh;
  position: fixed;
  top: 50%;
  left: 50%;
  display: none;
  transform: translate(-50%, -50%);
}

根据要求。

  • 如何将 :hover:after 显示的图像放入其父容器中? - 通过知道父容器的宽度并在content 伪元素上设置相同的宽度,在这种情况下使用 vh 和 vw 并使用相同的图像尺寸
  • 如何使用 :hover:after 响应式显示图像? - 与之前相同,但您也可以查看背景大小以将图像拉伸到位。
  • 如何让元素在取消悬停后淡出? - 不幸的是,我认为我们必须使用 JS 来实现这一点。

附上小提琴供参考。fiddle here

注意:出于演示目的,很少有 li 元素会被设为不可悬停

其他参考链接,CSS-Tricks articleSO question on pseudo element visibility

【讨论】:

  • 谢谢!我看着小提琴,它确实非常接近预期的效果。当图像显示而不是位于其他选项之上时,是否可以让图像独立?就像现在一样,除非用户点击其他地方,否则触摸屏会卡在 :hover 中。即使图像占据了自己的空间,情况仍然如此,但其他选项仍然可见,用户可以点击这些选项。
  • 我也想避开js。
【解决方案5】:

body {
background: #ccd;
color: #fff;

}

.damn {
width:80%;
height:80%;
border: 1px solid black;
position:absolute;
top:50%;
left: 50%;
transform: translate(-50%, -50%);
display:flex;
align-items:center;
justify-content:center;
}
.controller{
padding:0;
margin:0;
list-style:none;
width:100%;
height:100%;
display:flex;
flex-direction:column;
flex-Wrap:wrap;
align-items:center;
justify-content:center;
}
.controller li {
background: #ddd;
list-style-type: none;
width:20%;
}
.controller li:nth-child(odd) {
	background: #000;
}
.controller li:hover {
	background: red;
}
.controller li:last-child{
background:#ccc;
width:80%;
height:100%;
padding:1%;}


/* content Control */
.imgWrap{
  border:1px solid blue;
  display:flex;
  overflow:hidden;
  align-items:center;
  justify-content:center;
}
#red:hover~.imgWrap{
content:url("http://www.markgray.com.au/images/gallery/large/desert-light.jpg");
}

#blue:hover~.imgWrap {
 content:url("https://www.hlf.org.uk/sites/default/files/styles/siftgroups_media_fullsize/public/media/programmes/landscape_partnerships_overlooking_the_wye_.jpg?itok=HOgiVAEW&width=800&height=600")}

#green:hover~.imgWrap { content:url("http://www.markgray.com.au/images/gallery/large/desert-light.jpg");
}
#yellow:hover~.imgWrap {
content:url("https://www.hlf.org.uk/sites/default/files/styles/siftgroups_media_fullsize/public/media/programmes/landscape_partnerships_overlooking_the_wye_.jpg?itok=HOgiVAEW&width=800&height=600")}

#orange:hover~.imgWrap { content:url("http://www.markgray.com.au/images/gallery/large/desert-light.jpg");
}
#white:hover~.imgWrap {
content:url("https://www.hlf.org.uk/sites/default/files/styles/siftgroups_media_fullsize/public/media/programmes/landscape_partnerships_overlooking_the_wye_.jpg?itok=HOgiVAEW&width=800&height=600")}

#black:hover~.imgWrap { content:url("http://www.markgray.com.au/images/gallery/large/desert-light.jpg");
}
<body>
	<div class="damn">
		<ul class="controller">
			<li id="red">Red</li>
			<li id="blue">Blue</li>
			<li id="green">Green</li>
			<li id="yellow">Yellow</li>
			<li id="orange">Orange</li>
			<li id="white">White</li>
			<li id="black">Black</li>
            <li id="showImg" class="imgWrap">a</li>
		</ul>
       
	</div>
</body>

它还没有过渡。它还没有响应。它只是一个简单的显示。还是要我把它放进去?

【讨论】:

  • Obnik,谢谢你的回答。容器确实像我想要的那样改变了它的大小,但是如果你调整它的大小,你会注意到它不会保持纵横比。另外,是的,如果可以添加我在问题中描述的所有元素,那么我很容易选择一个完整的答案。
猜你喜欢
  • 2017-10-24
  • 2021-08-07
  • 2021-01-01
  • 2021-10-23
  • 1970-01-01
  • 2015-09-09
  • 2011-03-08
  • 2013-02-24
  • 2020-02-02
相关资源
最近更新 更多