阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      width/height 作用的具体细节

      一 ,深藏不露的 width:auto

      width:auto 在不同场景下的宽度表现

      • (1)充分利用可用空间。比方说,< div>、< p>这些元素的宽度默认是 100% 于父级容器的。这种充分利用可用空间的行为还有个专有名字,叫作 fill-available,大家了解即可。

      • (2)收缩与包裹。典型代表就是浮动、绝对定位、inline-block 元素或 table 元素, 英文称为 shrink-to-fit,直译为“收缩到合适”。CSS3 中的 fit-content 指的就是这种宽度表现。

      • (3)收缩到最小。这个最容易出现在 table-layout 为 auto 的表格中,

      当每一列空间都不够的时候,文字能断就断,但中文是随便断的,英文单词不能断。于是,第一列被无情地每个字都断掉,形成一柱擎天。

      这种行为在规范中被描述为“preferred minimumwidth”或者“minimum content width”。后来还有了一个更加好听的名字 min-content。

      • (4)超出容器限制。除非有明确的 width 相关设置,否则上面 3 种情况尺寸都不会主动超过父级容器宽度的,但是存在一些特殊情况。

      例如,内容很长的连续的英文和数字,或者内联元素被设置了 white-space:nowrap。

      .father {
          width: 150px;
          background-color: #cd0000;
          white-space: nowrap;
      }
      .child {
          display: inline-block;
          background-color: #f0f3f9;
      }
      

      子元素既保持了 inline-block 元素的收缩特性,又同时让内容宽度最大,直接无视父级容器的宽度限制。这种现象后来有了专门的属性值描述,这个属性值叫作 max-content,

      这个属于 CSS3 内容,作者提了下,没有继续开展。

      1.1 外部尺寸与流体特性

      上面 4 种尺寸表现,哪个是“外部尺寸”?哪个是“内部尺寸”?

      答:就第一个,也就是<div>默认宽度 100%显示,是“外部尺寸”,其余全部是“内部尺寸”。

      而这唯一的“外部尺寸”,是“流”的精髓所在。

      1 正常流宽度

      这里,作者指出了一些冗余的写法

      a {
          display: block;
          width: 100%;
      }
      

      这里display: block;本身就是全宽度展开的,没有必要再次写width: 100%;;

      并列举了一个文档流的导航

      <style>
          .left-area {
              width: 800px;
          }
      
          .nav {
              background-color: #cd0000;
          }
      
          .nav-a {
              display: block;
              margin: 0 10px;
              padding: 9px 10px;
              border-bottom: 1px solid #b70000;
              border-top: 1px solid #de3636;
              color: #fff;
          }
      
          .nav-a:first-child {
              border-top: 0;
          }
      
          .nav-a+.nav-a+.nav-a {
              border-bottom: 0;
          }
      </style>
      <div class="left-area">
          <div class="nav">
              <a href="" class="nav-a">导航1</a>
              <a href="" class="nav-a">导航2</a>
              <a href="" class="nav-a">导航3</a>
          </div>
      </div>
      

      这么写是文档流流无宽度布局,就算外面容器left-area尺寸变化,我们的导航也可以自适应,这就是充分利用浏览器原生流特性的好处。

      这种布局,注重:无宽度,无图片,无浮动

      与之相反的一个布局是写死宽度的,这种写法是每次改都要重新计算width的;

      .nav {
          width: 240px;
      }
      .nav-a {
          display: block;
          /* 200px = 240px - 10px*2 - 10px*2 */
          width: 200px;
          margin: 0 10px;
          padding: 9px 10px;
          ...
      }
      

      2 格式化宽度

      这种情况是脱离文档流场景下的;也就是出现在 position属性值为 absolute 或 fixed 的元素中。

      在默认情况下,绝对定位元素的宽度表现是“包裹性”,宽度由内部尺寸决定,但是,有一种情况其宽度是由外部尺寸决定的,

      对于非替换元素(见本书第 4 章),当 left/top 或 top/bottom 对立方位的属性值同时存在的时候,元素的宽度表现为“格式化宽度”,

      其宽度大小相对于最近的具有定位特性(position 属性值不是 static)的祖先元素计算。

      div { position: absolute; left: 20px; right: 20px; }
      

      假设该< div>元素最近的具有定位特性的祖先元素的宽度是 1000 像素,

          因为 left 和 right 是对立的
      

      则这个 < div>元素的宽度是 960(即 1000−20−20)像素。

      此外,和上面的普通流一样,“格式化宽度”具有完全的流体性,也就是 margin、border、padding 和 content 内容区域同样会自动分配水平(和垂直)空间。

      “格式化宽度”水很深,同时也非常实用,更多内容可参见本书第 6 章与 position:absolute 相关的内容。

      1.2 内部尺寸与流体特性

      上讲的是“外部尺寸”,本节就讲讲“内部尺寸”。

      所谓“内部尺寸”,简单来讲就是元素的尺寸由内部的元素决定,而非由外部的容器决定。

      如何快速判断一个元素使用的是否为“内部尺寸”呢?很简单,

      假如这个元素里面没有内容,宽度就是 0,那就是应用的“内部尺寸”。

      1. 包裹性/自适应性

      作者造了一个词"包裹性",我感觉叫"自适应性"更好;

      “自适应性”,指的是元素尺寸由内部元素决定,但永远小于“包含块”容器的尺寸;

      对于一个元素,如果其 display 属性值是 inline-block,那么即使其里面内容再多,只要是正常文本,宽度也不会超过容器。

      于是,图文混排的时候,我们只要关心内容,除非“首选最小宽度”比容器宽度还要大,否则我们完全不需要担心某个元素内容太多而破坏了布局;

      按钮就是这样的;(注:<button>标签按钮才会自动换行,<input>标签按钮,默认 white-space:pre,是不会换行的,需要将 pre 值重置为默认的 normal。)

      自适应性对实际开发有什么作用如下?

      页面某个模块的文字内容是动态的,可能是几个字,也可能是一句话。然后,希望文字少的时候居中显示,文字超过一行的时候居左显示。

      <div class="box">
        <p id="conMore" class="content">文字内容-新增文字-新增文字-新增文字</p>
      </div>
      
      <style>
      .box {
        padding: 10px;
        background-color: #cd0000;
        text-align: center;
      }
      .content {
        display: inline-block;
        text-align: left;
      }
      </style>
      

      2. 首选最小宽度

      所谓“首选最小宽度”,指的是元素最适合的最小宽度。

      外部容器的宽度假设宽度是0,请问里面的 inline-block 元素的宽度是多少?是 0 吗?不是。

      在 CSS 世界中,图片和文字的权重要远大于布局,因此,CSS 的设计者显然是不会让图文在 width:auto 时宽度变成 0 的,此时所表现的宽度就是“首选最小宽度”。

      • 东亚文字(如中文)最小宽度为每个汉字的宽度,
      • 西方文字最小宽度由特定的连续的英文字符单元决定。并不是所有的英文字符都会组成连续单元,一般会终止于空格(普通空格)、短横线、问号以及其他非英文字符等。例如,“display:inline-block”这几个字符以连接符“-”作为分隔符,形成了“display:inline”和“block”两个连续单元,由于连接符“-”分隔位置在字符后面,因此,最后的宽度就是“display:inline-”的宽度,
        • 如果想让英文字符和中文一样,每一个字符都用最小宽度单元,可以试试使用 CSS 中的 word-break:break-all。
      • 类似图片这样的替换元素的最小宽度就是该元素内容本身的宽度。

      3. 最大宽度

      这个感觉没啥太大用处,了解即可;

      上面讲的都是width:auto

      二 ,width 值作用的细节

      首先了解 盒子模型,见下图

      作者强行用地球构造来比喻盒子模型,感觉增加了理解难度,简单问题复杂化了,这个比喻不建议看。作者引出的:“内在盒子”又被分成了 4 个盒子,分别是 content box、padding box、border box和 margin box;这个观点,建议新手不要尝试死磕,这节只需要理解下面一句话就可以了

      盒子本身的尺寸不会因 margin值变化而变化,但border/padding/content尺寸的改变,均会影响盒子尺寸;

      <div>元素默认的 padding、border 和 margin 都是 0,如果我们在水平方向给定 padding 和 border 大小,则元素的宽度就会改变;

      (1)流动性丢失

      如果设置了宽度,则会影响文档流(并不会脱离文档流),比如再1920PX像素下,设置宽度为920;会被截断,导致右侧的1000像素没有任何元素显示在那里;(这也是设置宽度的特性)

      (2)与现实世界表现不一致的困扰。

      设置边框和内边距会在总宽度基础上增加;

      日常使用软件,画一个宽度为140px的矩形,边框是2px,这时候默认画出来是包含边框的140px;而CSS写需要写宽度136px,边框2px;

      (CSS3种有一种新的盒子模型,原理类似日常习惯,是下面第四部分讲的box-sizing: border-box;

      三 ,CSS 流体布局下的宽度分离原则

      宽度分离

      作者提出的这个写法非常值得了解

      需求:写一个包含1px边框的102px总宽度矩形;;你写完以后又告诉你,希望元素边框内有 20 像素的留白

      普通写页面,

      .box {
          width: 100px;
          border: 1px solid;
      }
      

      再改为

      .box {
          width: 60px;  // 通过计算,减去 40 像素
          padding: 20px;
          border: 1px solid;
      }
      

      而用宽度分离的方法写页面就非常爽(CSS实用小技巧)

      .father {
          width: 102px;
      }
      .son {
          border: 1px solid;
      }
      

      再改为

      .father {
          width: 102px;
      }
      .son {
          border: 1px solid;
          padding: 20px;//新增就好
      }
      

      这样的写法,浪费一个父级的HTML标签;当时感觉如果按照这个思路些;维护性更好;做自适应的页面,逻辑会更清晰;

      四 ,改变 width/height 作用细节的 box-sizing

      这个图可以直观说明,就是设置100px宽度,则表示内容+边框+padding+margin的总宽度是100px;

      下面这种总宽度也是100px;

      .box {
          width: 100px;
          box-sizing: border-box;
          padding: 20px;
          border: 1px solid;
      }
      

      注意:这个写法,margin是不支持的,如果你的两个盒子有margin;需要外面再套一层进行计算(好尴尬啊);

      这个属性非常适合 原生普通文本框<input>和文本域<textarea>

      不错的用途;

      拿文本域<textarea>举例,<textarea>为替换元素,替换元素的特性之一就是尺寸由内部元素决定,且无论其 display 属性值是 inline 还是 block。这个特性很有意思,对于非替换元素,如果其 display 属性值为 block,则会具有流动性,宽度由外部尺寸决定,但是替换元素的宽度却不受 display 水平影响,因此,我们通过 CSS 修改<textarea>的display 水平是无法让尺寸 100%自适应父容器的:

      textarea {
          display: block; /* 还是原来的尺寸 */
      }
      

      所以,我们只能通过 width 设定让<textarea>尺寸 100%自适应父容器。那么,问题就来了,<textarea>是有 border 的,而且需要有一定的 padding 大小,否则输入的时候光标会顶 着边框,体验很不好。于是,width/border 和 padding 注定要共存,同时还要整体宽度 100%自适应容器。如果不借助其他标签,肯定是无解的。

      下面这样写就非常不错(CSS实用小技巧)

      textarea {
          width: 100%;
          -ms-box-sizing: border-box; /* for IE8 */
          box-sizing: border-box;
      }
      

      五 ,相对简单而单纯的 height:auto

      比较简单,正常就是自适应;没有宽度那么复杂;

      六 ,关于 height:100%

      插入一个< div>,然后满屏显示背景图(CSS实用小技巧)

      下面是错误的写法

      div {
          width: 100%; /* 这是多余的 */
          height: 100%; /* 这是无效的 */
          background: url(bg.jpg);
      }
      

      正确的写法

      //仅仅设置<body>也是不行的,因为此时的<body>也没有具体的高度值:
      html, body {
          height: 100%;
      }
      div {
          background: url(bg.jpg);
          height: 100%;
      }
      

      原理:对于 height 属性,如果父元素height 为 auto,只要子元素在文档流中,其百分比值完全就被忽略了。

      为何 height:100%无效

      规范中其实给出了答案。如果包含块的高度没有显式指定(即高度由内容决定),并且该元素不是绝对定位,则计算值为auto。一句话总结就是:因为解释成了 auto。要知道,auto 和百分比计算,肯定是算不了的

      如何让元素支持 height:100%效果

      (1)设定显式的高度值

      html, body {
          height: 100%;
      }
      

      (2)使用绝对定位。

      div {
          height: 100%;
          position: absolute;
      }
      
      目录
      目录