跳到主要内容

三栏

2023年01月23日
柏拉文
越努力,越幸运

一、Flex 布局


场景背景: 实现一个左宽为200px, 右宽自适应的两栏布局

场景解决: 通过项目 flex: 1 实现(flex: 1 === flex: 1 1 0)

实时编辑器
function Test(props) {
    const containerStyle = {
            width: '100%',
            height: '300px',
            backgroundColor: 'red',
            display: 'flex',
        }
        const leftStyle = {
            flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
            width: "200px",
            backgroundColor: "blue"
        }
        const centerStyle = {
            flex: 1, // flex: 1 === flex: 1 1 0 即会缩短,也会伸长
            backgroundColor: "yellow"
        }
        const rightStyle = {
            flex: "none", // flex: none === flex: 0 0 auto  不会缩短,也不会伸长
            width: "200px",
            backgroundColor: "blue"
        }

        return (
            <div style={ containerStyle }>
                <div style={ leftStyle }></div>
                <div style={ centerStyle }></div>
                <div style={ rightStyle }></div>
            </div>
        );
}
结果
Loading...

二、Grid 布局


场景背景: 实现一个左宽为200px, 右宽为200px, 中间自适应的三栏布局

场景解决: 通过 grid-template-columns: 200px auto 200px 实现

实时编辑器
function Test(props) {
    const containerStyle = {
        width: '100%',
        height: '300px',
        backgroundColor: 'red',
        display: 'grid',
        gridTemplateColumns: '200px auto 200px',
    }
    const leftStyle = {
        backgroundColor: "yellow"
    }
    const centerStyle = {
        backgroundColor: "green"
    }
    const rightStyle = {
        backgroundColor: "blue"
    }

    return (
        <div style={ containerStyle }>
            <div style={ leftStyle }></div>
            <div style={ centerStyle }></div>
            <div style={ rightStyle }></div>
        </div>
    );
}
结果
Loading...

三、Table 布局


场景背景: 实现一个左宽为200px, 右宽为200px, 中间自适应的三栏布局

场景解决: 给父元素设置display: table, 给自适应子元素设置width: 100%; display: table-cell;

实时编辑器
function Test(props) {
    const containerStyle = {
            width: '100%',
            height: '300px',
            display: 'table',
            backgroundColor: 'red',
        }
        const leftStyle = {
            width: "200px",
            height: "100%",
            backgroundColor: "yellow"
        }
        const centerStyle = {
            width: "100%",
            height: "100%",
            display: "table-cell",
            backgroundColor: "blue"
        }
        const rightStyle = {
            width: "200px",
            height: "100%",
            backgroundColor: "yellow"
        }

        return (
            <div style={ containerStyle }>
                <div style={ leftStyle }></div>
                <div style={ centerStyle }></div>
                <div style={ rightStyle }></div>
            </div>
        );
}
结果
Loading...

四、Float 布局


4.1 margin-left、right 正值方案

解决方案: 左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后。

实时编辑器
function Test(props) {
  const container = {
    width: "800px",
    height: "400px",
    backgroundColor: "red"
  }
  const left = {
    width: "200px",
    height: "100%",
    float: "left",
    backgroundColor: "blue"
  }
  const center = {
    width: "auto",
    height: "100%",
    marginLeft: "200px",
    marginRight: "200px",
    backgroundColor: "black"
  }
  const right = {
    width: "200px",
    height: "100%",
    float: "right",
    backgroundColor: "yellow"
  }

  return (
     <div style={ container }>
       <div style={ left }></div>
       <div style={ right }></div>
       <div style={ center }></div>
     </div>
  );
}
结果
Loading...

4.2 padding、margin、position 圣杯布局方案

解决方案: 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。

实时编辑器
function Test(props) {
  const container = {
    width: "800px",
    height: "400px",
    paddingLeft: "200px",
    paddingRight: "200px",
    backgroundColor: "red"
  }
  const left = {
    width: "200px",
    height: "100%",
    float: "left",
    marginLeft: "-100%",
    position: "relative",
    left: "-200px",
    backgroundColor: "blue"
  }
  const center = {
    width: "100%",
    height: "100%",
    float: "left",
    backgroundColor: "black"
  }
  const right = {
    width: "200px",
    height: "100%",
    float: "right",
    marginLeft: "-200px",
    position: "relative",
    left: "200px",
    backgroundColor: "yellow"
  }

  return (
     <div style={ container }>
       <div style={ center }></div>
       <div style={ left }></div>
       <div style={ right }></div>
     </div>
  );
}
结果
Loading...

4.3 padding、margin、wrapper 双飞翼布局方案

解决方案: 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。

实时编辑器
function Test(props) {
  const container = {
    width: "800px",
    height: "400px",
    backgroundColor: "red"
  }
  const left = {
    width: "200px",
    height: "100%",
    float: "left",
    marginLeft: "-100%",
    backgroundColor: "blue"
  }
  const centerWrap = {
    width: "100%",
    height: "100%",
    float: "left",
    backgroundColor: "black"
  }
  const center = {
    width: "auto",
    height: "100%",
    marginLeft: "200px",
    marginRight: "200px",
  }
  const right = {
    width: "200px",
    height: "100%",
    float: "left",
    marginLeft: "-200px",
    backgroundColor: "yellow"
  }

  return (
     <div style={ container }>
        <div style={ centerWrap }>
            <div style={ center }></div>
        </div>
       <div style={ left }></div>
       <div style={ right }></div>
     </div>
  );
}
结果
Loading...

参考资料


「2021」高频前端面试题汇总之CSS篇