发布于 2026-01-06 7 阅读
0

CSS 优先级和 !important 的使用:案例研究 DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

CSS 特殊性及 !important 的使用:案例研究

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

最近,推特上出现了一个投票,提问者询问粉丝关于 CSS 优先级的问题。可惜我没找到原推文(如果你找到了,请在下方留言!),但简单来说,大多数人都答错了。

那次 Twitter 投票(及其后续影响)促使我重新学习了有关特异性的知识,进而让我开始着手解决自己项目中的特异性问题,这也引出了我写这篇文章的目的。 

在这篇文章中,我们将重构我项目中的 CSS 代码,该项目存在需要修复的 CSS 优先级问题。

CSS 特异性

定义

MDN Web Docs 将特异性描述为“浏览器决定哪些 CSS 属性值与元素最相关,因此应用这些属性值的方式”。

规则

浏览器在决定哪些 CSS 属性值最适合应用于某个元素时,会根据 CSS 样式表的源顺序(即层叠顺序)来判断。但这条规则只适用于 CSS 选择器优先级相同的情况。如果一个 CSS 选择器的优先级高于另一个,会发生什么呢?

在这种情况下,浏览器会根据 CSS 选择器的优先级来决定应用哪些 CSS 语句。CSS 选择器的优先级越高,浏览器就越有可能优先应用它的 CSS 声明。

nav a {
  color: green;
}
a {
  color: red;
}

例如,在上面的例子中,两个 CSS 选择器都指向同一个 HTML 元素——锚点标签。为了确定应该对锚点标签应用哪条 CSS 规则,浏览器会计算它们的优先级值,并检查哪个优先级最高。在本例中,第一个选择器的优先级值更高,因此浏览器会使用第一个选择器的规则来对锚点标签应用。 

这里需要指出的是,虽然 `!important` 不是 CSS 选择器,但它是一个关键字,用于强制覆盖 CSS 规则,而不管 CSS 选择器的优先级、来源或源顺序如何。一些使用场景包括:

  • 临时补救措施(有点像用胶带粘住漏水的水管)

  • 覆盖内联样式

  • 用于测试/调试目的

虽然使用 `!important` 关键字看似有用,但实际上弊大于利。随着时间的推移,它会使 CSS 代码难以维护,并严重影响样式表的可读性,尤其对于将来使用该样式表的其他人而言。 

这就引出了我们今天要做的事情——解决项目中的具体性问题。

项目

简单介绍一下我们将要重构的项目——这是一个受 Netflix 启发、使用 MovieDB API 的登录页面。 

样式表

目标是通过重构代码,使其遵循优先级规则,从而从应用了“!important”关键字的 CSS 规则中删除该关键字。 

下面显示的是该项目的样式表。

@import url("https://fonts.googleapis.com/css?family=Montserrat:400,400i,700");
body {
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}
.wrapper {
  width: 100%;
}
.wrapper #header {
  position: fixed;
  z-index: 300;
  padding: 15px;
  width: calc(100% - 30px);
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: linear-gradient(to bottom, black 0%, transparent 100%);
}
.wrapper #header #brand-logo {
  color: #d32f2f;
  text-shadow: 1px 1px 2px black;
  letter-spacing: 5px;
  text-transform: uppercase;
  font-family: Montserrat;
  font-weight: bold;
  font-size: 22px;
}
.wrapper #header #menu-icon {
  display: none;
}
.wrapper #header .nav-link,
.wrapper #header .icon {
  color: #bdbdbd;
  cursor: pointer;
}
.wrapper #header .nav-menu {
  width: 400px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}
.wrapper #header .nav-link {
  padding: 5px 10px;
  font-size: 15px;
  font-family: century gothic;
  text-decoration: none;
  transition: background-color 0.2s ease-in;
}
.wrapper #header .nav-link:hover {
  color: #c62828;
  background-color: rgba(0, 0, 0, 0.7);
}
.wrapper #header .icon {
  font-size: 16px;
}
.wrapper #header .icon:hover {
  color: #c62828;
}
.wrapper #site-banner,
.wrapper #categories {
  width: 100%;
}
.wrapper #site-banner {
  height: 550px;
  background-image: url("https://s1.gifyu.com/images/rampage_2018-1024x576.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
.wrapper #site-banner .main-movie-title,
.wrapper #site-banner .watch-btn,
.wrapper #site-banner .main-overview {
  position: absolute;
  z-index: 3;
}
.wrapper #site-banner .main-movie-title, .wrapper #site-banner .watch-btn {
  text-transform: uppercase;
}
.wrapper #site-banner .main-movie-title {
  top: 120px;
  left: 20px;
  background: -webkit-linear-gradient(#ff9100, #dd2c00);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  font-size: 55px;
  font-family: Montserrat;
  font-weight: bold;
}
.wrapper #site-banner .main-overview {
  width: 400px;
  top: 230px;
  left: 25px;
  color: #fafafa;
  line-height: 25px;
  font-family: helvetica;
}
.wrapper #site-banner .watch-btn {
  width: 150px;
  height: 35px;
  top: 350px;
  left: 25px;
  border: none;
  border-radius: 20px;
  color: #fafafa;
  cursor: pointer;
  transition: all 0.2s ease-in;
  background-color: #ff0000;
  box-shadow: 1px 5px 15px #940000;
}
.wrapper #site-banner .watch-btn:hover {
  color: #F5F5F5;
  background-color: #940000;
}
.wrapper .after {
  position: relative;
  top: 0;
  left: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.3);
}
.wrapper #categories {
  padding: 30px 0;
  display: flex;
  flex-direction: column;
  background: linear-gradient(to top, #090909 0%, #000000 100%);
  overflow: hidden;
}
.wrapper #categories .category {
  margin: 30px 0;
}
.wrapper #categories .category-header, .wrapper #categories .content {
  margin-left: 20px;
  color: #B0BEC5;
  font-family: helvetica;
}
.wrapper #categories .category-header {
  margin-bottom: 50px;
  font-weight: normal;
  letter-spacing: 5px;
}
.wrapper #categories .content {
  position: relative;
  right: 0;
  display: flex;
  justify-content: flex-start;
  transition: all 3s ease-in-out;
}
.wrapper #categories .movie {
  margin-right: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}
.wrapper #categories .movie-img {
  transition: all 0.2s ease-in;
}
.wrapper #categories .movie-img:hover {
  -webkit-filter: contrast(1.1);
          filter: contrast(1.1);
  -webkit-transform: scale(1.05);
          transform: scale(1.05);
  cursor: pointer;
}
.wrapper #footer {
  width: 100%;
  height: 120px;
  background-color: #090909;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
}
.wrapper #footer #copyright-label {
  margin-left: 20px;
  padding: 10px;
  color: rgba(255, 255, 255, 0.3);
  opacity: 0.7;
  letter-spacing: 2px;
  font-family: helvetica;
  font-size: 12px;
}
//Media Query
@media (max-width: 750px) {
  .nav-menu {
    visibility: hidden;
  }
#menu-icon {
    display: block !important;
    font-size: 22px;
  }
.main-movie-title {
    font-size: 45px !important;
  }
.main-overview {
    width: 350px !important;
    font-size: 14px !important;
  }
.watch-btn {
    width: 130px !important;
    height: 25px !important;
    font-size: 13px;
  }
.movie-img {
    width: 170px;
  }
}

因此,从样式表中我们可以看出,!important 关键字的使用主要集中在媒体查询部分,该部分概述了当屏幕宽度小于 750 像素时浏览器应应用的样式。 

那么,如果我们从应用了 `!important` 关键字的 CSS 规则中移除它会发生什么呢?这样一来,我们就失去了强制覆盖其他指向同一 HTML 元素的 CSS 选择器的“王牌”。因此,浏览器会检查样式表,看看是否存在任何冲突的 CSS 规则。 

如果存在冲突的 CSS 选择器,浏览器会根据 CSS 选择器的源顺序、优先级和重要性来确定应用哪条规则。如果冲突的 CSS 选择器优先级相同,浏览器会遵循源顺序规则,应用样式表中位置较低的 CSS 选择器的规则。根据这些信息,我们可以看出,我们的样式表并不存在这种情况。

但是,如果冲突的 CSS 选择器具有不同的优先级,浏览器会应用优先级更高的 CSS 选择器的规则。我们可以从样式表中看到这种情况;媒体查询中的 CSS 选择器优先级低于样式表主体部分的 CSS 选择器。

既然我们已经找到了问题所在,那就让我们来解决它吧!

首先,我们需要找到与媒体查询中的 CSS 选择器相匹配的对应 CSS 选择器。

.wrapper #header #menu-icon {
  display: none;
}
.wrapper #site-banner .main-movie-title {
  ...
  font-size: 55px;
  ...
}
.wrapper #site-banner .main-overview {
  width: 400px;
  ...
}
.wrapper #site-banner .watch-btn {
  width: 150px;
  height: 35px;
  ...
}
@media (max-width: 750px) {
#menu-icon {
    display: block !important;
    ...
  }
.main-movie-title {
    font-size: 45px !important;
  }
.main-overview {
    width: 350px !important;
    font-size: 14px !important;
  }
.watch-btn {
    width: 130px !important;
    height: 25px !important;
    ...
  }
}

我们可以看到,样式表主体部分的 CSS 选择器比媒体查询中对应的 CSS 选择器具有更高的优先级。尽管媒体查询中的 CSS 选择器在样式表中出现得更靠后,但由于优先级规则(优先级规则优先于源顺序规则),浏览器会应用位于其前面的 CSS 选择器的规则。为了解决这个问题,我们必须提高媒体查询中 CSS 选择器的优先级值。如果我们使指向相同 HTML 元素的 CSS 选择器具有相同的优先级,那么浏览器将遵循源顺序规则;当屏幕宽度小于 750 像素时,将应用位于样式表下方的媒体查询中定义的 CSS 规则。 

最终效果如下:

.wrapper #header #menu-icon {
  display: none;
}
.wrapper #site-banner .main-movie-title {
  ...
  font-size: 55px;
  ...
}
.wrapper #site-banner .main-overview {
  width: 400px;
  ...
}
.wrapper #site-banner .watch-btn {
  width: 150px;
  height: 35px;
  ...
}
@media (max-width: 750px) {
.wrapper #header #menu-icon {
    display: block;
    ...
  }
.wrapper #site-banner .main-movie-title {
    font-size: 45px;
  }
.wrapper #site-banner .main-overview {
    width: 350px;
    font-size: 14px;
  }
.wrapper #site-banner .watch-btn {
    width: 130px;
    height: 25px;
    font-size: 13px;
  }
}

就这样!我们已经从样式表中移除了所有与 `!important` 关键字相关的代码。现在我们可以看到样式表更易于阅读了,您可以想象,重构后的样式表将更便于使用和维护,尤其是在其他人也需要使用它的情况下。

结论

那么,我们学到了什么? 

我们已经了解了浏览器如何通过选择器的源顺序、优先级和来源来确定要应用哪些 CSS 样式。我们也了解了在 CSS 中使用 `!important` 可能出现的问题,以及为什么应该尽量减少它的使用。 

我们不必使用 !important 来解决问题——还有更好的解决方案。 

理解“特异性”的概念可能需要一段时间,但我希望通过记录过程并使用一个真实的项目,能够帮助你更好地理解“特异性”的概念以及如何在自己的 CSS 中应用它。

其他资源

您可以在这里找到我们一直在进行的项目

希望你喜欢这篇文章!如果喜欢,请点赞❤️、💬并分享!下次见! ✌️

文章来源:https://dev.to/munamohamed94/css-specificity-and-the-use-of-important-a-case-study--11