CSS样式中奇奇怪怪的问题

426 阅读4分钟

在学习 CSS 样式的过程中总会遇到令人费解的 CSS 样式问题,比如行内元素与块元素不同的特性导致的覆盖问题,又或者十分经典的 margin 塌陷问题及 margin 合并问题,这些都是学习前端 CSS 中不可避免的,因此本文记录了一些在学习过程中遇到的 CSS 样式问题及解决方法以供参考。

行内元素内边距覆盖其他元素

行内元素<span><a>它们的宽度和高度是无法指定的,而是根据其内容自动收缩适应。不过行内元素是可以指定内边距的,然而当给行内元素设置的上下内边距太大时,可能会覆盖到其他元素,这一点与块级元素有所不同。

<div>
  <div id="d">Hello, World!</div>
  <span>这是行内元素</span>
</div>
#d {
  height: 50px;
  background-color: gray;
}
span {
  background-color: orange;
  /* 给行内元素设置过大的内边距 */
  padding: 20px 10px;
}
image.png

如果既要保留行内元素的特性又不想造成覆盖其他元素这样的情况,可以将元素指定为行内块元素

span {
  display: inline-block;
}
image.png

margin 塌陷问题

margin 塌陷问题是 CSS 样式中相当经典的样式问题。
首先定义一个.outer块元素,两个.inner子元素:

<div class="outer">
  <div class="inner"></div>
  <div class="inner"></div>
</div>

然后给这些元素添加一些样式作区分:

.outer {
  width: 200px;
  height: 200px;
  background-color: gray;
}
.inner {
  width: 50px;
  height: 50px;
}
.inner:first-child {
  background-color: bisque;
}
.inner:nth-child(2) {
  background-color: orange;
}

此时它们的排布如下:
image.png

尝试给第一个.inner子元素添加margin-top,让其相对于.outer向下偏移:

.inner:first-child {
  margin-top: 50px;
  background-color: bisque;
}

实际效果是.outer整体向下偏移:
image.png

如果给第二个.inner子元素添加margin-bottom,试图让其向上偏移,那么整体都不移动。
这是一个历史遗留的问题,导致子元素的margin-topmargin-bottom交给了父元素。
解决方案:

  1. .outer添加border: 1px solid transparent
  2. .outer添加padding: 1px
  3. .outer添加overflow: hidden

前两种方法虽然可以解决 margin 塌陷问题,不过也会导致有1px的间隙,所以不是很推荐;最后一种则没有其他的样式影响,是最好的方式。
image.png

margin 合并问题

margin 合并问题与 margin 塌陷问题如出一辙,也是margin相关的 CSS 样式问题。 首先定义两个块元素,它们都是边长100px的正方形:

<div class="box box1"></div>
<div class="box box2"></div>

这些元素添加样式如下:

.box {
  width: 100px;
  height: 100px;
}
.box1 {
  background-color: orange;
}
.box2 {
  background-color: gray;
}

它们的样式呈现如下:
image.png

尝试让两个块元素的间距为50px+60px

.box {
  width: 100px;
  height: 100px;
}
.box1 {
  background-color: orange;
  margin-bottom: 50px;
}
.box2 {
  background-color: gray;
  margin-top: 60px;
}

实际上,它们的间距为60px
image.png

margin的合并问题会出现在上下相邻的两个块元素间。这样的问题只能规避:

  • 给第二个元素添加:float: left
  • 只给一个元素设置margin,不要同时有margin-bottommargin-top image.png

CSS处理内容溢出

当给了块元素限制的高度或宽度时,内容区的东西太多会溢出到块元素外。

<div>
    Hello, World!!!!Hello, World!!!!
</div>

给块元素限制的高度或宽度:

div {
    width: 100px;
    height: 20px;
    background-color: gray;
}

实际效果:
image.png

可以解决的方法:

div {
  /* hidden auto visible scroll */
  overflow: hidden;
  overflow-left: auto;
  overflow-right: visible; 
}

CSS元素的空白间距问题

行内元素和行内块元素之间因为换行会导致之间留一个空白间隙。
如下,分别有行内元素<span>和行内块元素img

<div>
  <span>hello</span>
  <span>world</span>
  <img>
  <img>
</div>

给这些元素指定样式:

span {
  background-color: orange;
}
img {
  width: 50px;
  height: 50px;
  background-color: gray;
}

在展示中,这些行内元素和行内块元素之间都有一个空白间隙:
image.png

实际上空白也是一个字符,而一个字符要么通过继承得到字体大小,要么就本身设定大小。 对于元素间的空白问题,如果要解决,则可以给父元素设置font-size: 0,然后单独给元素设置font-size: 16px

div {
  font-size: 0;
}
span {
  font-size: 16px;
}
image.png

CSS行内块元素的幽灵空白问题

CSS 行内块元素的幽灵空白问题就是:有时候行内块元素如img底部贴着父元素,有时候其底部与父元素有一个空白间隙。实际上这主要与对齐方式有关。
首先 HTML 中有一个字符 “x” 和一个行内块元素img

<div id="d1">
  x
  <img>
</div>

给它们分别添加样式作区分:

img {
    width: 50px;
    height: 50px;
    background-color: blue;
}

#d1 {
    background-color: gray;
}

会看到蓝色块与底边有一个间距:
image.png

实际上这是因为与 x 基线对齐的原因,解决方案通常只能作规避。

  1. 与行内元素+行内块元素的垂直居中一样,添加vertical-align: middle;
img {
    width: 50px;
    height: 50px;
    background-color: blue;
    vertical-align: middle;
}
image.png
  1. 或者将行内块元素设置为块元素,display: block;
img {
    width: 50px;
    height: 50px;
    background-color: blue;
    display: block;
}
image.png