• HTML & CSS – Styling List


    前言

    ul > li 经常会用到, 它原本的 style 很丑, 这篇介绍如果修改它.

    以前学 W3Schools 的时候也有记入过: HTML – W3Schools 学习笔记

    参考:

    Youtube – HTML & CSS for Beginners Part 17: How to Create and Style HTML Lists

    Youtube – Styling your list-items just got so much easier with this pseudo-element!

    Youtube – Next-Level List Bullets With CSS ::marker

    Custom bullets with CSS ::marker

    HTML 默认

    <div class="container">
      <ul>
        <li>item1</li>
        <li>item2</li>
      </ul>
    </div>

     效果

    红框是 container 范围. 整个 ul 默认有一个 padding-left 40px. 

    如果有写 reset CSS 的话, 那么它的 padding 通常是 0

    bullet 会神奇的跑出去...

    list-style-type

    常见的 type 有: circle, alpha, roman, decimal

    甚至可以直接写 string 哦

    li {
      list-style-type: "> ";
    }

    效果

    list-style-position

    它的功能是设置 bullet 是在 inside 还是 outside, 默认是 outside.

    padding-left: 40px 的长相:

    padding-left: 0 的长相:

    inside 有个体验问题, 第 2 行的字没有和第一行对齐, 反而跑到了 bullet 的区域, 这样很不整齐..

    Tailwind CSS 的解释图, 非常清晰:

    Custom Styling

    use Flex

    设置 list-style-type: none. 在 HTML/CSS 写 icon 用 Flex 做间距.

    .container {
      border: 1px solid black;
      width: fit-content;
      min-width: 200px;
    
      padding: 0.5rem;
      ul {
        list-style-type: none;
        li {
          &::before {
            font: var(--fa-font-solid);
            content: "\f00c";
            padding-right: 0.25rem;
          }
        }
      }
    }

    效果

    用 Flex 的好处是直观, 最大的问题是 align-items. Flex 只能 center 或者 baseline, 没用办法做法 vertical-align: middle

    当 bullet 和 text 的大小不一致又有 2 行 text 时, 就会有麻烦了.

    除非我们知道 line-height 那就可以在 icon wrap 一层居中 icon. 但 hardcode line-height 不顺风水, 不同 font-family line-height 是不太一样的, lh unit 目前又还不支持.

    目前无解.

    use pseudo background image

    参考: codepen example

    li :: before 这种做法在 text 有 2 行的时候, 第 2 行会在 icon 下面. 解决方法是定位 (但是这个很不顺风水)

    use ::marker

    如果只是想换 icon 用 build-in 的 ::marker 会很方便, 虽然它没有 cover 100% 场景 (不支持 margin, padding), 但是通常够用了.

    ul {
      font-size: 2rem;
      li {
        padding-left: 0.5rem;
      }
      ::marker {
        color: red;
        font: var(--fa-font-solid);
        content: "\f00d";
      }
    }

    marker 可以选中 bullet, 然后就可以自定义内容了. 上面用了 fontawesome 的 code. 效果:

    也可以换成 text, url(svg..) 等等

    ::marker {
      color: red;
      content: "> " counter(list-item);
    }

    还可以配上 counter 输出 index 哦.

    它有 2 个问题

    1. svg sprite 不行, 还有 svg 的 width, height 无法通过 font-size 控制 (即使在 svg 里写 1em 也没用, 可能是 ::marker 搞的鬼吧), 总之理想的做法是用 fontawesome

    2. 当 icon 和 text 大小不一致时, 需要把 text 用 span wrap 起来然后设置 vertical-align: middle

    注: 这个操作会导致 line-height 变大到 1.4 左右哦,

    而且必须是 display: inline, inline-block 会变成 align center (like Flex), block 会变成 baseline

    stackoverflow – Vertically align smaller bullets with larger text

    use list-style-image

    参考: MDN – list-style-image

    最大的问题是 svg 的大小无法用 CSS 控制. 只能写死在 svg 里

    注意事项

    1. icon, text 大小不一致时要 vertical-align 或 aligh-items

    2. Flex, icon 要 flex-shrink:0 当遇到 2 行时它无法像 vertical-align 那样居中

    3. svg 不管用 ::marker, ::before, list-style-image 都不顺, 尽可能用 fontawesome, 真的没办法就用 HTML svg + Flex 方案

    4. 最佳方案是 ::marker 配 fontawesome, icon text 大小不一致时需要 vertical-alight: middle

    间距问题

    有 2 个间距挺烦人的,

    第 1 个是 bullet 和 container 的间距.

    ul 默认 position outside, bullet 不占据空间, 它依靠 padding-left 40px 把 bullet 弄出来.

    但是这个 padding-left 不容易控制, 通常放 1.2em, 2ch, 或者 same font-size with bullet, 如果是字, 比如 "Step 1:" 用 ch 比较准. 但也只是大概准而已.

    它的关键就在于 bullet 不占位子. 得靠 padding, 而这个 padding 就依赖 bullet 的大小, 然后只可以大概调.

    如果用 inside 的话, 它就会刚刚好, 但是 second line 就对不齐了

    我本来以为, 自己搞 Flex 就可以搞定这个对齐的问题. 后来我发现并不那么容易. 

    假如我们用 icon 替代 bullet, 然后让 li > icon + text, 在 li 做 Flex.

    这个时候 vertical align 就难搞了. 这个 bullet 小于 text, 它又在 text 的中心, 这个是 vertical-align: middle 才做的到. 而 flex 只能 align-items: baseline. 

    除非我们知道 line-height 那就可以在 icon wrap 一层居中 icon. 但 hardcode line-height 不顺风水, 不同 font-family line-height 是不太一样的, lh unit 目前又还不支持.

    第 2 个是 bullet 和 text 的间距.

    这个是通过 li padding-left 控制的. ::marker 是写不到 padding 和 margin 的哦. 

    也有人通过 content: '\空格' 来实现.  .

    相关参考:

    stackoverflow – How to keep indent for second line in ordered lists via CSS?

    CSS – Indenting the second line of LI (List Items)

    description list (dl > dt + dd)

    <dl>
      <dt>Coffee</dt>
      <dd>Black hot drink</dd>
      <dt>Milk</dt>
      <dd>White cold drink</dd>
    </dl>

    默认样式

    它会一左一右是因为有 margin

    但这种一高一低一左一右, 真的很丑. 所以很多人都问怎样让它一左一右就好. 类似 key value pair

    stackoverflow – How to style dt and dd so they are on the same line?

    首先是 standard 的 reset CSS, 去掉原本的 margin

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    然后用 Flex 就可以了

    dl {
      display: flex;
      flex-wrap: wrap;
      row-gap: 1rem;
    
      dt {
        flex: 0 0 50%;
      }
      dd {
        flex: 0 0 50%;
      }
    }

    其原理是让每个 item 占据 50%, 那么 1 row 最多只能容纳 2 个 item, 也就是 1 个 dt 和 1 个 dd. 

    然后剩余的就 wrap 往下掉. 再做一个 row-gap 让 row 有 spacing 就可以了

    Grid 的写法也是更简单

    dl {
      display: grid;
      grid-template-columns: 1fr 1fr;
      row-gap: 1rem;
    }

    Float 的写法

    dt,
    dd {
      &:nth-child(n + 3) {
        margin-top: 1rem;
      }
       50%;
      float: left;
    }
  • 相关阅读:
    iOS基础
    iOS基础 ----- 内存管理
    NSAttributedString 的一些基本用法
    node安装使用
    docker常用命令
    docker lnmp
    easy-wechat
    composer
    center7系统搭建lnmp
    xammp环境配置
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15968934.html
Copyright © 2020-2023  润新知