有时候,我希望能够使用CSS选择父元素,而在这个问题上我并不孤单 。 但是,CSS中没有“ 父选择器”之类的东西,因此暂时无法实现。
在本教程中,我们将介绍一些使用CSS父选择器的情况,以及一些可能的解决方法。 让我们开始吧!
等一下,什么是家长选择器?
CSS选择器使我们能够定位元素,在DOM树中向下移动并在此过程中变得更加具体。 这是您可能在Bootstrap中找到的一种选择器的示例-它沿着DOM树从nav.navbar-dark
元素向下移动到ul
, li
,最后是a.nav-link
。
.navbar-dark .navbar-nav .nav-item .nav-link {
}
家长选择将允许我们旅行回来了 DOM,针对某些事情的父元素。 例如,我们可以使用以下方法定位.nav-link
元素的父对象:
.nav-link::parent {
}
注意:此示例是纯伪代码,它不存在也不建议最佳语法!
情况1:样式化旧内容
在重新设计网站时,具有旧标记和结构的旧内容样式是经典的挑战。 例如,在HTML5之前,图像通常可能已经用p
, div
或有时用span
以及用于包裹图像标题的嵌套p
包裹。 没有包装图像和标题的标准方法。 后来,我们采用了figure
和figcaption
元素,使我们的文档结构更具语义。
我们希望来自旧内容的图像如上所示。 但是由于我们的文档中可能有更多的div
标签,而这些标签根本不包含图像,因此以下样式声明将是完全不切实际的。
.page-content div {
padding: 15px;
background-color: #f3f3f3;
margin: 10px 0 20px;
}
.page-content div img {
marging: 0 0 10px;
}
.page-content div .img-caption {
color: #999;
font-size: 12px;
text-align: center;
Wisplay: block;
}
它将背景颜色,填充和边距应用于内容中的所有div元素。 实际上,我们实际上想将这些样式专门应用于包装图像和图像标题的div
元素。
情况2:保持视频比率
另一个示例着眼于保持嵌入式视频(例如来自Youtube或Vimeo的视频)的比率,以及使视频流畅。 如今,很大程度上要归功于Dave Rupert和pals的调查工作,人们普遍认为,最好的方法是对父元素应用padding-top
或padding-bottom
。
但是,在现实世界中,我们可能不知道哪个元素包含视频。 我们可能会发现一些包裹在div
或p
嵌入式视频,但没有可识别的类名,这使得选择适当的元素来应用样式非常困难。
因此,按照以下方式声明样式也是不切实际的,因为这会影响.page-content
所有div,包括不包含嵌入式视频的div。
.page-content {
width: 560px;
margin-right: auto;
margin-left: auto;
margin-top: 30px;
}
.page-content div {
position: relative;
padding-bottom: 56.25%;
}
.page-content div iframe {
position: absolute;
top: 0;
width: 100%;
height: 100%;
}
直接选择视频的父元素将是多么美妙!
情况3:响应表单输入
在此示例中,我们有一个包含多个输入的表单。 当我们专注于其中一个输入时,将获得更加突出的边框颜色,突出显示用户在表单中的位置。
有时,您可能还会遇到这样一种情况,不仅边框颜色突出,而且包装输入的元素也被突出显示,从而使输入更加突出:
父元素可以是div
或p
。 那么,如何根据后代的某些状态正确选择父元素呢?
可能的解决方法
正如我们所介绍的,没有父选择器之类的东西,因此无法选择父项。 通过完全重新考虑设计,避免选择父代,我们可能会回避这个问题。 但是,如果这不可能,那么这里有一些潜在的方法。
使用CSS :has()
选择器
:has
选择器正式称为关系伪类 。 它根据在圆括号之间定义的后代来匹配元素。
在下面的示例中,它将background-color
应用于包含图像标题的任何div
。 这似乎解决了案例1。
.page-content div:has( .img-caption ) {
padding: 15px;
background-color: #ccc;
}
或者,如果我们想更具体一点,我们可以重写它以匹配任何以.img-caption
为直接后代的div
标签。
.page-content div:has( > .img-caption ) {
padding: 15px;
background-color: #ccc;
}
尽管没有浏览器实现此选择器,但它是为CSS选择器级别4起草的。 我们将需要稍等一会儿,此选择器才会显示出来。 在此之前,请观看以下视频课程,标题为“未来CSS”,以了解选择器的工作原理:
- :具有伪类
- 结合:具有和:不
使用jQuery父选择器
没有任何CSS解决方案可以在这里解决我们的问题,因此让我们看看JavaScript可以为我们做什么。 在此示例中,我们将使用jQuery的强大API,便利性和浏览器兼容性。 在撰写本文时,jQuery提供了三种选择父元素的方法。
parent()
; 此方法选择目标元素的直接父级。 我们可以利用这种方法来解决本教程前面提到的所有用例。
例如,我们可以使用parent()
向内容中图像的包装元素添加特殊类。
$( ".img-caption" )
.parent()
.addClass( "has-img-caption" );
上面的代码将选择包裹图像的直接元素,而不管元素的类型如何,并添加has-img-caption
类,以使我们对元素的选择和样式有更多的控制,如下所示。
parents()
注意此方法的复数形式。 此方法允许我们从直接对象到文档的根目录中选择父元素,除非指定了选择器作为参数。
$( ".img-caption" )
.parents()
.addClass( "has-img-caption" );
在上面的示例中, parents()
方法从div
标签中选择所有方式,该标签立即包装图像,下一个div
和最后一个html
,将has-img-caption
类添加到所有元素。
这样的过度杀伤是多余的。 在这种情况下,唯一可能需要添加类的元素是立即div
元素。 因此,我们将其传递给method参数。
$( ".img-caption" )
.parents( "div" )
.addClass( "has-img-caption" );
在这里, parents()
方法将遍历图像的祖先树,选择找到的任何div
并为其赋予has-image-caption
类。
如果仍然无法忍受,则可以通过指定索引将选择范围缩小到单个元素。 在以下示例中,我们仅将类应用于第一个div
。
var $parents = $( ".caption" ).parents( "div" );
$parents[0].addClass( "has-img-caption" ); // select the first div add add the class.
parentsUntil()
; 此方法选择的父元素最多但不包括括号中指定的元素。
$( ".caption" )
.parentsUntil( ".page-content" )
.addClass( "has-img-caption" );
给定上面的代码,它将has-img-caption
类应用于除.page-content
元素之外的所有父元素。
在某些情况下,如果您拥有数以parentsUntil()
嵌套元素,则最好使用parentsUntil()
方法。 相比较而言,它比parents()
方法要快,因为它避免了使用jQuery选择器引擎(Sizzle)遍历整个DOM树直到文档根。
结语
将来某个时候,我们是否可能会有CSS父选择器?
可能不是。 我们上面讨论的那种父选择器已经被提出了很多次,但是由于多种原因,它从未通过W3C草案阶段。 由于浏览器评估和呈现页面的方式,这些原因主要集中在浏览器性能上。 我们将来最接近的是关系选择器:has()
。
但是,由于:has()
尚不适用,因此JavaScript和jQuery当前是最可靠的方法。 请记住,DOM遍历是一项代价高昂的操作,可能会严重影响您网站的渲染性能。 避免与其他繁重的操作(如animate()
, fadeIn()
或fadeOut()
parentsUntil()
一起使用parents()
或parentsUntil()
fadeOut()
。
更好的是,尽可能检查HTML结构,看看是否可以完全避免选择父元素!