Flexible Box - flexbox

 

Flexible Box是CSS3的新東西,最主要的目的是提供一個工具,讓開發者對網頁佈局更便利。

 

display

在CSS3中對display還增加了兩個種方式可設定,分別為flex與inline-flex,

單看display內屬性值的比較,你可以把flex看成是block一樣的作用,可以把inline-flex看成是inline-block一樣的作用,

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="author" content="Brookes">
    <meta name="copyright" content="Brookes">
    <title>Brookes</title>
    <style>
        .flex {
            display: flex;
            background: #c00;
        }

        .inline-flex {
            display: inline-flex;
            background: #069;
        }

    </style>
</head>
<body>
    <div class="flex">display:flex</div>
    <span>test</span>
    <br>
    <br>
    <div class="inline-flex">display:inline-flex</div>
    <span>test</span>
</body>
</html>

使用display:flex;或display:inline-flex;其目的在於把該元素宣告成flexible items,

才可以使用flex的進階功能。

 

一、在父元素設定上的 flex 效果

1、flex-direction

flex-direction可以決定flexbox內容元素的排列方向與順序,

其值可為row(預設值)、row-reverse、column、column-reverse

a、row:使用flex-direction為row的元素,其子元素的排列方向為由左開始排到右

b、row-reverse:使用flex-direction為row-reverse的元素,其子元素的排列方向為由右開始排到左

c、column:使用flex-direction為column的元素,其子元素的排列方向為由上開始排到下

d、column-reverse:使用flex-direction為column-reverse的元素,其子元素的排列方向為由下開始排到上

<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="author" content="Brookes">
    <meta name="copyright" content="Brookes">
    <title>Brookes</title>
    <style>
        .row {
            flex-direction: row;
        }

        .row-reverse {
            flex-direction: row-reverse;
        }

        .column {
            flex-direction: column;
        }

        .column-reverse {
            flex-direction: column-reverse;
        }

        .flex {
            display: flex;
            width: 120px;
            height: 120px;
            border: 1px solid #000;
        }

        .flex-item {
            width: 30px;
            height: 30px;
            text-align: center;
            line-height: 30px;
        }

        .item1 {
            background: blue;
        }

        .item2 {
            background: red;
        }

        .item3 {
            background: green;
        }
    </style>
</head>

<body>
    <div class="flex row">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>

    <div class="flex row-reverse">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>

    <div class="flex column">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>

    <div class="flex column-reverse">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
</body>
</html>

Tips:

a、row 與 row-reverse 的水平排列控制屬性是 justify-content,垂直排列控制屬性是 align-items。

b、column 與 column-reverse 的水平排列控制屬性是 align-items,垂直排列控制屬性是 justify-content。

 

2、justify-content

與 align-items 屬性相對,

justify-content可以決定flexbox內容元素的排列分部,

其值可為flex-start(預設值)、flex-end、center、space-between、space-around

a、flex-start:靠左排列(main-start)

b、flex-end:靠右排列(main-end)

c、center:水平往中央靠攏

d、space-between:子元素與空白間距也平均排列,而左右元素會貼靠在父元素的邊界(main-start與main-end)

e、space-around:子元素與空白間距也平均排列,每個子元素的都會有等寬的左右間距。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="author" content="Brookes">
    <meta name="copyright" content="Brookes">
    <title>Brookes</title>
    <style>
        .flex-start,
        .flex-end,
        .center,
        .space-between,
        .space-around {
            display: flex;
            width: 300px;
            height: 60px;
            margin: 10px;
            border: 1px solid #000;
        }

        .flex-start {
            justify-content: flex-start;
        }

        .flex-end {
            justify-content: flex-end;
        }

        .center {
            justify-content: center;
        }

        .space-between {
            justify-content: space-between;
        }

        .space-around {
            justify-content: space-around;
        }

        .flex-item {
            width: 50px;
            height: 50px;
            text-align: center;
            line-height: 50px;
        }

        .item1 {
            background: blue;
        }

        .item2 {
            background: red;
        }

        .item3 {
            background: green;
        }
    </style>
</head>
<body>
    <div class="flex-start">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="flex-end">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="center">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="space-between">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="space-around">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
</body>
</html>

 

3、align-items

與 justify-content 屬性相對,

align-items可以決定flexbox內容元素的排列位置,

a、flex-start:靠上排列(cross-start)

b、flex-end:靠下排列(cross-end)

c、center:垂直往中央靠攏

d、stretch:為預設值。所有子元素內容高度延伸至占滿父元素空間。

e、baseline:以各元素文字為基線,如下圖。以最高子元素的基線作為對齊標準。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="author" content="brookes">
    <meta name="copyright" content="brookes">
    <title>brookes</title>
    <style>
        .flex-start,
        .flex-end,
        .center,
        .stretch,
        .baseline {
            display: inline-flex;
            width: 100px;
            height: 120px;
            margin: 5px;
            border: 1px solid #000;
            vertical-align: top;
        }

        .flex-start {
            align-items: flex-start;
        }

        .flex-end {
            align-items: flex-end;
        }

        .center {
            align-items: center;
        }

        .stretch {
            align-items: stretch;
        }

        .baseline {
            align-items: baseline;
        }

        .flex-item {
            width: 30px;
            text-align: center;
        }

        .item1 {
            padding: 30 0px;
            background: red;
        }

        .item2 {
            padding: 20 0px;
            background: blue;
        }

        .item3 {
            padding: 40 0px;
            background: green;
        }
    </style>
</head>

<body>
    <div class="flex-start">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="flex-end">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="center">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="stretch">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
    <div class="baseline">
        <div class="flex-item item1">1</div>
        <div class="flex-item item2">2</div>
        <div class="flex-item item3">3</div>
    </div>
</body>
</html>

 

4、align-content

先前已介紹align-items(垂直排列)與justify-content(水平排列),

那如果想要同時擁有垂直與水平排列的特性則要使用align-content,

align-content 是針對「多列」的排列方法,

其值可為flex-start(預設值)、flex-end、center、space-between、space-around、stretch

a、flex-start:靠上排列(cross-start)

b、flex-end:靠下排列(cross-end)

c、center:水平垂直置中

d、space-between:子元素與空白間距也平均排列,而左右元素會貼靠在父元素的邊界(main-start與main-end)

e、space-around:子元素與空白間距也平均排列,每個子元素的都會有等寬的左右間距。

f、stretch:所有子元素內容高度延伸至占滿父元素空間。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="author" content="brookes">
    <meta name="copyright" content="brookes">
    <title>brookes</title>
    <style>
        .flex-start,
        .flex-end,
        .center,
        .space-between,
        .space-around,
        .stretch {
            display: inline-flex;
            flex-wrap: wrap;
            width: 180px;
            height: 160px;
            margin: 5px 5px 40px;
            border: 1px solid;
            vertical-align: top;
        }

        .flex-start {
            align-content: flex-start;
        }

        .flex-end {
            align-content: flex-end;
        }

        .center {
            align-content: center;
        }

        .space-between {
            align-content: space-between;
        }

        .space-around {
            align-content: space-around;
        }

        .stretch {
            align-content: stretch;
        }

        .align-content > div {
            padding: 15px;
            margin: 2px;
            background: lightblue;
        }
    </style>
</head>

<body>
    <div class="flex-start align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
    <div class="flex-end align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
    <div class="center align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
    <div class="space-between align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
    <div class="space-around align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
    <div class="stretch align-content">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
        <div>6</div>
    </div>
</body>
</html>

 

5、flex-wrap

用來讓子元素們換行,其值可為nowrap(預設值,單行)、wrap(多行)、wrap-reverse(多行,但內容元素反向排列),

範例可參考上例。

 

6、flex-flow 簡寫

flex-flow 是 flex-direction 和 flex-wrap 的簡寫,文法如下:

flex-flow: flex-direction flex-wrap|initial|inherit;

 

二、在子元素設定上的 flex 效果

1、order

這個屬性可用來強制指定排列順序。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="author" content="brookes">
    <meta name="copyright" content="brookes">
    <title>brookes</title>
    <style>
        .flex {
            display: flex;
            width: 180px;
            height: 60px;
            margin: 5px 5px 40px;
            border: 1px solid #000;
            vertical-align: top;
        }

        .item {
            width: 50px;
            height: 60px;
            text-align: center;
            line-height: 50px;
        }

        .order1 {
            order: 1;
            background: blue;
        }

        .order2 {
            order: 2;
            background: red;
        }

        .order3 {
            order: 3;
            background: green;
        }

        .order4 {
            order: 4;
            background: yellow;
        }

        .order5 {
            order: 5;
            background: gray;
        }

        .order6 {
            order: 6;
            background: lightblue;
        }
    </style>
</head>

<body>
    <div class="flex">
        <div class="item order2">1</div>
        <div class="item order4">2</div>
        <div class="item order6">3</div>
        <div class="item order1">4</div>
        <div class="item order3">5</div>
        <div class="item order5">6</div>
    </div>
</body>
</html>

 

2、align-self

引用w3cSchool的範例

<!DOCTYPE html>
<html>
<head>
    <style>
        .flex-container {
            display: flex;
            height: 200px;
            background-color: #f1f1f1;
            align-items: flex-end;
        }

            .flex-container > div {
                background-color: DodgerBlue;
                color: white;
                width: 100px;
                margin: 10px;
                text-align: center;
                line-height: 75px;
                font-size: 30px;
            }
    </style>
</head>
<body>

    <div class="flex-container">
        <div>1</div>
        <div>2</div>
        <div style="align-self: center">3</div>
        <div>4</div>
    </div>

    <p>An item with the align-self property set to <em>center</em> will center align the item.</p>

    <p>The align-self property overrides the align-items property of the container.</p>

</body>
</html>

align-self 的設定與 align-items 相同,但align-self 的作用在於個別指定 align-items 的方式,

亦可覆寫已經套用align-items的屬性。

 

三、展示範例

個人製作了此範例來展示在 CSS 的

display、justify-content、align-items、flex-direction 屬性交互作用下所呈現的效果。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <meta name="author" content="Brooke">
    <meta name="copyright" content="Brooke">
    <title>Brooke</title>
    <style>
        .row {
            flex-direction: row;
        }

        .row-reverse {
            flex-direction: row-reverse;
        }

        .column {
            flex-direction: column;
        }

        .column-reverse {
            flex-direction: column-reverse;
        }

        .flex {
            display: flex;
            width: 120px;
            height: 120px;
            border: 1px solid #000;
        }

        .item1 {
            background: blue;
        }

        .item2 {
            background: red;
        }

        .item3 {
            background: green;
        }
    </style>
</head>
<body>
    <fieldset>
        <legend>display</legend>
        <input type="radio" id="flex" name="display" checked />
        <label for="flex">flex</label>
        <input type="radio" id="inline-flex" name="display" />
        <label for="inline-flex">inline-flex</label>
    </fieldset>

    <fieldset>
        <legend>justify-content</legend>
        <input type="radio" id="justify-content-flex-start" name="justify-content" checked />
        <label for="justify-content-flex-start">flex-start</label>
        <input type="radio" id="justify-content-flex-end" name="justify-content" />
        <label for="justify-content-flex-end">flex-end</label>
        <input type="radio" id="justify-content-center" name="justify-content" />
        <label for="justify-content-center">center</label>
        <input type="radio" id="justify-content-space-between" name="justify-content" />
        <label for="justify-content-space-between">space-between</label>
        <input type="radio" id="justify-content-space-around" name="justify-content" />
        <label for="justify-content-space-around">space-around</label>
    </fieldset>

    <fieldset>
        <legend>align-items</legend>
        <input type="radio" id="align-items-flex-start" name="align-items" />
        <label for="align-items-flex-start">flex-start</label>
        <input type="radio" id="align-items-flex-end" name="align-items" />
        <label for="align-items-flex-end">flex-end</label>
        <input type="radio" id="align-items-center" name="align-items" />
        <label for="align-items-center">center</label>
        <input type="radio" id="align-items-stretch" name="align-items" checked />
        <label for="align-items-stretch">stretch</label>
        <input type="radio" id="align-items-baseline" name="align-items" />
        <label for="align-items-baseline">baseline</label>
    </fieldset>

    <div class="flex row">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
    </div>

    <div class="flex row-reverse">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
    </div>

    <div class="flex column">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
    </div>

    <div class="flex column-reverse">
        <div class="item1">1</div>
        <div class="item2">2</div>
        <div class="item3">3</div>
    </div>

    <script>
        var styles = [
            {
                name: "display",
                tuple: [{
                    id: "flex",
                    value: "flex"
                },
                {
                    id: "inline-flex",
                    value: "inline-flex"
                }]
            },
            {
                name: "justifyContent",
                tuple: [{
                    id: "justify-content-flex-start",
                    value: "flex-start"
                },
                {
                    id: "justify-content-flex-end",
                    value: "flex-end"
                },
                {
                    id: "justify-content-center",
                    value: "center"
                },
                {
                    id: "justify-content-space-between",
                    value: "space-between"
                },
                {
                    id: "justify-content-space-around",
                    value: "space-around"
                }]
            },
            {
                name: "alignItems",
                tuple: [{
                    id: "align-items-flex-start",
                    value: "flex-start"
                },
                {
                    id: "align-items-flex-end",
                    value: "flex-end"
                },
                {
                    id: "align-items-center",
                    value: "center"
                },
                {
                    id: "align-items-stretch",
                    value: "stretch"
                },
                {
                    id: "align-items-baseline",
                    value: "baseline"
                }]
            },
        ];

        for (var k = 0; k < styles.length; k++) {
            for (var i = 0; i < styles[k].tuple.length; i++) {
                (function (i, k) {
                    document.getElementById(styles[k].tuple[i].id).addEventListener("click", function myfunction() {
                        var flexes = document.getElementsByClassName("flex");
                        for (var j = 0; j < flexes.length; j++) {
                            flexes[j].style[styles[k].name] = styles[k].tuple[i].value;
                        }
                    });
                })(i, k);
            }
        }

    </script>
</body>
</html>

 

參考資料:

Flex Layout Box Model and Terminology

CSS参考手册

Test CSS Flexbox Rules Live

CSS Flexible Box Layout Module

CSS flex Property

A Complete Guide to Flexbox