深入理解css 笔记(5)

创造浮动的初衷并不是为了用于页面布局。浮动能将一个元素,通常是一张图片,拉到其容器的一侧,这样文档流就能够包围它。word 文档中,报纸,杂志中很常见。所以 css 增加了浮动来实现这种效果。尽管这才是浮动的是设计初衷,我们却并不总是这样使用它。flexbox 正在迅速取代浮动在页面布局中的地位。flexbox 的行为很直观,可预测行更好。不过了解一下,而且浮动的初衷,要实现将图片移动道网页一侧,并且让文字围绕图片的效果,浮动仍然是唯一的方法。

<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <meta
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
      name="viewport"
    />
    <style>
      :root {
        box-sizing: border-box;
      }

      *,
      :before,
      :after {
        box-sizing: inherit;
      }

      body {
        background-color: #eee;
        font-family: Arial, Helvetica, sans-serif;
      }

      body * + * {
        margin-top: 1.5em;
      }

      header {
        color: #fff;
        background-color: #0072b0;
        padding: 1em 1.5em;
        border-radius: 0.5em;
        margin-bottom: 1.5em;
      }

      .main {
        background-color: #fff;
        border-radius: 0.5em;
        padding: 1em 1.5em;
      }

      .container {
        max-width: 1080px;
        margin: 0 auto;
      }

      .media {
        float: left;
        width: 50%;
        padding: 1.5em;
        background-color: #eee;
        border-radius: 0.5em;
      }
    </style>
  </head>

  <body>
    <div class="container">
      <header>
        <h1>Running Club</h1>
      </header>

      <main class="main clearfix">
        <h2>Running tips</h2>
        <div>
          <div class="media">
            <img class="media-image" src="hi.png" />
            <div class="media-body">
              <h4>Strength</h4>
              <p>
                Strength training is an important part of injury prevention.
                Focus on your core &mdash; especially your abs and glutes.
              </p>
            </div>
          </div>

          <div class="media">
            <img class="media-image" src="hi.png" />
            <div class="media-body">
              <h4>Cadence</h4>
              <p>
                Check your stride turnover. The most efficient runners take
                about 180 steps per minute.
              </p>
            </div>
          </div>

          <div class="media">
            <img class="media-image" src="hi.png" />
            <div class="media-body">
              <h4>Change it</h4>
              <p>Don't run the same every time you hit the road.</p>
            </div>
          </div>

          <div class="media">
            <img class="media-image" src="hi.png" />
            <div class="media-body">
              <h4>Focus on form</h4>
              <p>
                RUn tall but relaxed.Your feet should hit the ground beneath
                your hips,
              </p>
            </div>
          </div>
        </div>
      </main>
    </div>
  </body>
</html>

  因为浮动元素不同于普通文档流元素,它们的高度不会加到父元素上。一种解决方法使用跟浮动配套的 clear 属性。将一个元素放在主容器的末尾,并对它使用 clear,这回让容器扩展到浮动元素下面。

<div style="clear:both"></div>

  clear:both 声明让该元素浮动到浮动元素的下面,而不是侧面。因为空 div 本身没有浮动,所以容器就会扩展,直到包含它,因此也会包含该 div 上面的浮动元素。这种方法能够实现预期的行为,但是不雅。要在 html 里添加不必要的标记,才能实现本应该由 Css 实现的效果。不用额外的 div 标签,我们还可以用伪元素来实现。使用::after 伪元素喧杂起,就可以快速的在 dom 中在容器末尾添加一个元素,而不用在 html 里添加标记。

<style>
  .clearfix:after {
    display: block;
    content: ' ';
    clear: both;
  }
</style>

  因为盒子高度不一致,浮动效果喝我们想象的不一致。我们真正想要的是每行有两个浮动盒子。想要修复这个问题很简单:清除第三个浮动元素上面的浮动。更通用的做法是,清除每行的第一个元素上面的浮动。由于已知每行有两个盒子,因此只需要清除每行的第奇数个元素上面那行的浮动即可。

<style>
  .media {
    float: left;
    margin: 0 1.5em 1.5em 0;
    width: calc(50% - 1.5em);
    padding: 1.5em;
    background-color: #eee;
    border-radius: 0.5em;
  }

  .media:nth-child(odd) {
    clear: left;
  }

  .clearfix::after {
    content: ' ';
    display: block;
    clear: both;
  }
</style>

  media 里面的内容,我们想的是让图片在一侧,一段文字出现在图片的旁边。这种布局有几种实现方案,包括 flexbox 喝表格布局,浮动也可以。

<style>
  .media-image {
    float: left;
    width: 50px;
  }

  .media-body {
    margin-top: 0;
  }

  .media-body h4 {
    margin-top: 0;
  }
</style>

  现在这种在图片较小,文字较多的情况下会形成环绕的样式,但是我们想要的是两个分割左右,为了实现这种布局,需要为正文建立一个块级格式化上下文。block formatting context.bfc.BFC 是网页的一块区域,元素基于这块区域布局。虽然 BFC 本身是环绕文档流的一部分,但它将内部的内容和外部上下文隔开。简而言之,BFC 里的内容不会跟外部的元素重叠或者相互影响。只要给创建 BFC,网页的布局就会符合预期。通常是给元素设置 overflow:hidden 或者 auto.

<style>
  .media-image {
    float: left;
    width: 50px;
    margin-right: 1.5em;
  }

  .media-body {
    margin-top: 0;
    overflow: auto;
  }

  .media-body h4 {
    margin-top: 0;
  }
</style>

  大部分流行的 css 框架包含了自己的网格系统。它们的实现细节各不相同,但是设计思想相同:在一个行容器里放置一个或多个列容器。列容器的类决定每列的宽度。通常网格系统的每行被划分为特定数量的列,一般是 12 个,但也可以是其他数。选取 12 作为列数是因为它能够被 2346 整除,组合起来足够灵活。现在变的更多,一般都是 24 个格子里。用网格系统改造下前面的网页。虽然这种做法比前面实现布局的方式烦琐,但是可以提高 css 的可复用性,所以还是值得的。

<style>
  .row::after {
    content: ' ';
    display: block;
    clear: both;
  }

  [class*=*'column-'] {
    float: left;
  }

  .column-1 {
    width: 8.33%;
  }
  .column-2 {
    width: 16.6667%;
  }
</style>

  第一个选择器,它是一个属性选择器,根据元素的 class 属性匹配元素。但是跟普通的类轩再起相比,它能写出更复杂的匹配规则。*=比较符可以匹配任意包含指定字符串的值。属性选择器匹配的范围比预期的更广。比如除了匹配列元素,上面的属性选择器还能匹配 column-header 这样的元素。为了避免这种情况,最好是将 column 作为保留字,这样就不会跟以上样式规则冲突了。

  给每个网格列添加左右内边距,创造间隔。把间隔交给网格系统实现,而不是让内部的组件自己实现,这样就能够在其他页面复用这套网格系统,不用再费心去实现间隔。

<style>
  [class*="column-*"]{
    float:left:
    padding:0 0.75em;
    margin-top:0
  }
</style>

  第一次学习 flexbox 时,有点像拿着高压水枪喝水,东西太多了,很难将所有属性记住。给元素添加 display:flex,该元素就变成了一个弹性容器。它的直接子元素变成了弹性子元素。弹性子元素默认时再同一行按照从左到右的顺序并排排列。弹性容器像块元素一样填满可用宽度,但是弹性子元素不一定填满其弹性容器的宽度。弹性子元素高度相等,该高度由它们的内容决定。与其他的 display 值,比如 inline,inline-block 等,只会影响到应用了该样式的元素,而 flexbox 则不一样。一个弹性容器能控制内部元素的布局。

  子元素按照主轴线排列,主轴的方向为主起点到主终点。x 轴。垂直于主轴的是副轴,方向是从上到下,副起点到副终点。

<!DOCTYPE html>
<html lang="cn" class="has-bottombar">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <meta
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
      name="viewport"
    />
    <style>
      :root {
        box-sizing: border-box;
      }

      *,
      :before,
      :after {
        box-sizing: inherit;
      }

      body {
        background-color: #709b90;
        font-family: Arial, Helvetica, sans-serif;
      }

      body * + * {
        margin-top: 1.5em;
      }

      .container {
        max-width: 1080px;
        margin: 0 auto;
      }
    </style>
  </head>

  <body>
    <div class="container">
      <header>
        <h1>Ink</h1>
      </header>

      <nav>
        <ul class="site-nav">
          <li><a href="/">Home</a></li>
          <li><a href="/features">Features</a></li>
          <li><a href="/pricing">Pricing</a></li>
          <li class="nav-right">
            <a href="/about">About</a>
          </li>
        </ul>
      </nav>

      <main class="flex">
        <div class="column-main tile">
          <h1>Team collaboration done right</h1>
          <p>
            Thousands of teams from all over the world turn to <b>Ink</b> to
            communicate and get things done.
          </p>
        </div>

        <div class="column-sidebar">
          <div class="tile">
            <form class="login-form">
              <h3>Login</h3>
              <p>
                <label for="username">Username</label>
                <input id="username" type="text" name="username" />
              </p>
              <p>
                <label for="password">Password</label>
                <input id="password" type="password" name="password" />
              </p>
              <button type="submit">Login</button>
            </form>
          </div>

          <div class="tile centered">
            <small>Starting at</small>
            <div class="cost">
              <span class="cost-currency">$</span>
              <span class="cost-dollars">20</span>
              <span class="cost-cents">.00</span>
            </div>
            <a class="cta-button" href="/pricing"> Sign up </a>
          </div>
        </div>
      </main>
    </div>
  </body>
</html>

  首先,给列表加上 display:flex。然后覆盖浏览器默认的列表样式和猫头鹰选择器设置的顶部外边距。同时添加颜色。

<style>
  .site-nav {
    display: flex;
    padding: 0.5em;
    padding-left: 0;
    list-style-type: none;
    background-color: #5f4b44;
  }

  .site-nav > li {
    margin-top: 0;
  }

  .site-nav > li > a {
    background-color: #cc6b5a;
    display: block;
    padding: 0.5em 1em;
    color: white;
    text-decoration: none;
  }
</style>

  现在菜单看起来比较单薄,加上内边距能让它变饱满一些。给容器和菜单链接都加上内边距后。flexbox 允许使用 margin:auto 来填充弹性子元素之间的可用空间。flexbox 允许将最后的菜单项移动道右侧。加上外边距后,菜单就完成了。

<style>
  .site-nav {
    display: flex;
    padding: 0.5em;
    list-style-type: none;
    background-color: #5f4b44;
    border-radius: 0.2em;
  }

  .site-nav > li {
    margin-top: 0;
  }

  .site-nav > li > a {
    background-color: #cc6b5a;
    display: block;
    padding: 0.5em 1em;
    color: white;
    text-decoration: none;
  }

  .site-nav > li + li {
    margin-left: 1.5em;
  }

  .site-nav > .nav-right {
    margin-left: auto;
  }
</style>

  外边距非常适合现在的场景,因为我们需要菜单项之间的间距不同。如果希望菜单项等间距,那么 justify-content 属性会是更好的方式。前面的代码使用外边距给弹性子元素设置了间距。可以使用 width 和 height 属性设置它们大小,但是比起 margin,width,height 这些常见属性,flexbox 提供了更多更强大的选项。

<style>
  .tile {
    padding: 1.5em;
    background-color: #fff;
  }

  .flex {
    display: flex;
  }

  .flex > * + * {
    margin-top: 0;
    margin-left: 1.5em;
  }

  .column-main {
    flex: 2;
  }

  .column-sidebar {
    flex: 1;
  }
</style>

  flex 属性控制弹性子元素在主轴方向的大小(在这里指的元素的宽度)。弹性子元素的 flex 属性其实包含了好几个选项。我们先通过最基础的用例熟悉一下这个属性。这里用 column-main 和 column-sidebar 类来指定两列,使用 flex 属性给两列分别赋予 2/3 和 1/3 的宽度。flex 属性是三个不同大小属性的简写:flex-grow,flex-shrink 和 flex-basis。

  flex-basis 定义了元素大小的基准值,即一个初始的主尺寸。flex-basis 属性可以设置为 width 值,包括 px,em,百分比。它的初始值是 auto,此时浏览器会检查元素是否设置了 width 属性值。如果有,则使用 width 的值作为 flex-basis 的值;如果没有,则用元素内容自身的大小。如果 flex-basis 的值不是 auto,width 属性会被忽略。

  每个弹性子元素的初始主尺寸确定后,它们可能需要在主轴方向扩大或缩小来适应弹性容器的大小。这时候就需要 flex-grow 和 flex-shrink 来决定缩放的规则。flex-grow 的值越大,元素的权重越高,也就会占据更大的剩余宽度。一个 flex-grow:2 的子元素增长的宽度为 flex-grow:1 的子元素的两倍。flex-shrink 属性与 flex-grow 遵循相似的原则。如果某个子元素为 flex-shrink:0,则不会收缩;如果值大于 0,则会收缩至不再溢出。按照 flex-shrink 值的比例,值越大的元素收缩的越多。

  flex 属性又很多用法。可以像前面的网页那样,用 flex-grow 或者 flex-basis 百分比定义每列的比例。圣杯布局。左右固定大小,中间填满的布局。实现比较困难。重点是,三列的高度相等,该高度取决于它们的内容。尽管浮动也能实现这种布局,但需要用一些晦涩又脆弱的技巧。flex 就会简单很多。

  flexbox 的另一个重要功能是能够切换主副轴方向,用弹性容器的 flex-direction 属性控制。它的初始值 row 控制子元素从左到右的方向排列;指定 flex-direction:column 能控制弹性子元素沿垂直方向排列。flexbox 还支持 row-reverse 让元素从右到左派里,column-reverse 让元素从下到上排列。

  给 column-main 添加一些标题和段落,就会发现主板块超出了右边板块的地步。flexbox 应该能让两列的高度相等,但是不起作用。因为右边栏内部的两个板块没有扩展到填满右边栏区域。上述场景的真正需求是让两列扩展到填满容器的高度。因此要将右边栏改为弹性容器,并设置 flex-direction:column。然后给里面的两个板块设置非 0 的 flex-grow 值。

<style>
  .column-sidebar {
    flex: 1;
    display: flex;
    flex-direction: column;
  }

  .column-sidebar > .tile {
    flex: 1;
  }

  .login-form h3 {
    margin: 0;
    font-size: 0.9em;
    font-weight: bold;
    text-align: right;
    text-transform: uppercase;
  }

  .login-form input:not([type='checkbox']):not([type='radio']) {
    display: block;
    width: 100%;
    margin-top: 0;
  }

  .login-form button {
    margin-top: 1em;
    border: 1px solid #cc6b5a;
    background-color: white;
    padding: 0.5em 1em;
    cursor: pointer;
  }
</style>

  还有很多选项可以偶尔派上用场。这些选项大多数跟弹性容器内弹性子元素的对齐或者间距相关。flex-direction 指定了主轴方向,副轴垂直于主轴。flex-wrap 指定了弹性子元素是否会在弹性容器内折行显示。flex-flow justify-content 控制子元素在主轴上的位置。align-items 控制子元素在副轴上的位置。align-content 如果开启了 flex-wrap,align0content 就会控制弹性子元素在副轴上的间距。如果子元素没有换行,就会忽略 align-content.flex-grow 整数,指定增长因子,决定子元素在主轴方向扩展的大小,用于填充未使用的空间.flex-shrink 整数,指定收缩因子,决定子元素在主轴方向收缩的大小,防止溢出。如果弹性容器开启了 flex-wrap,则会忽略该属性.flex-basis。指定子元素未受 flex-grow 或 flex-shrink 影响时的初始大小.align-self 控制子元素在副轴上的对齐方式,它会覆盖容器上的 align-items 值。order:整数,将弹性子元素从兄弟节点中移动道指定位置,覆盖源码顺序。

<style>
  .centered {
    text-align: center;
  }

  .cost {
    display: flex;
    justify-content: center;
    align-items: center;
    line-height: 0.7;
  }

  .cost > span {
    margin-top: 0;
  }

  .cost-currency {
    font-size: 2rem;
  }

  .cost-dollars {
    font-size: 4rem;
  }

  .cost-cents {
    font-size: 1.5rem;
    align-items: flex-start;
  }

  .cta-button {
    display: block;
    background-color: #cc6b5a;
    color: white;
    padding: 0.5em 1em;
    text-decoration: none;
  }
</style>

  

posted @ 2022-10-16 14:27  艾路  阅读(22)  评论(0编辑  收藏  举报