顯示具有 Bootstrap 標籤的文章。 顯示所有文章
顯示具有 Bootstrap 標籤的文章。 顯示所有文章

2017年10月19日

[BS] Bootstrap 4 自訂容器和欄間距寬度(Custom Container and Gutters Width)

圖片來源:The Hack Today
tags: bootstrap4, container, layout, gutter
這篇文章主要是說明 Bootstrap 4 中 .container 的作用,以及 .col 間的間距(gutters)是如何產生的。最後則說明如何自訂自己想要寬度的 container 容器和欄間距。因此不會介紹太多關於 Bootstrap layout 的內容,關於 Bootstrap Layout 的介紹可以參考中文官方文件
註1:閱讀前希望你先知道 FlexBootstrap Container 的基本用法。
註2:以下說明均是以 max-width: 1140px 的情況說明(.col-xl)。
註3:可搭配 程式範例 @ CodePen
註4:如果是要套用到全域的話,請參考文末。

See the Pen Dive into Bootstrap4 Container by PJCHEN (@PJCHENder) on CodePen.

基本的 Bootstrap Container 結構

簡單來說,Bootstrap Container 基本的結構長這樣:
<!-- HTML -->
<div class="container">
    <div class="row">
        <div class="col">
            <div class="h4">
                Lorem ipsum dolor sit amet consectetur.
            </div>
        </div>
    </div>
</div>
畫面則會長這樣子:
Imgur
接下來讓我們看一下這些樣式主要的作用是什麼。

.container

從 Bootstrap 4 原始當中可以看到,.container 的樣式大概是這樣子:
.container {
  margin-right: auto;
  margin-left: auto;
  padding-right: 15px;
  padding-left: 15px;
  width: 100%;
  max-width: 1140px;      // 隨螢幕尺寸而變,當螢幕尺寸 ≥ 1200px 時是 1140px。
}
其中 .containermargin-rightmargin-left 是 auto,這是讓它可以水平置中的緣故。
接著當螢幕尺寸為 xl(≥1200px )時, 因為 max-width 是 1140px,而且有 padding-rightpadding-left 各 15px ,所以 :
  • 容器寬為 1140px(如果是使用 .container-fluid 則沒有設定 max-width
  • 內容寬為 1110px
  • 左右多於的空間自動分配給 margin
我們用 Chrome Dev Tool 看一下大概會長這樣子,有幾點可以注意的是:
  • 左右 margin 100 會隨著螢幕的寬度自動伸縮
  • 容器寬雖然是 1140px,但是由於有 padding 15px 的緣故,所以實際上內容的寬度是 1110px
Imgur
容器寬雖然是 1140px,但是由於有 padding 15px 的緣故,所以實際上內容的寬度是 1110px

.row

透過 .row 會讓裡面的內容以 flex 方式排版,原本在 .container 的作用下,內容寬會是 1110px ,但是因為有 margin-rightmargin-left-15px 的緣故,所以:
  • 容器寬為 1140px
  • 內容寬為 1140px
.row {
  display: flex;
  flex-wrap: wrap;
  margin-right: -15px;
  margin-left: -15px;
}
Imgur
原本在 .container 的作用下內容寬會是 1110px ,但是因為有 margin-rightmargin-left -15px 的緣故,所以容器和內容寬度均變回 1140px。

.col

.col.row 的 flex-item。在剛剛 .row 的作用下,.col 的容器寬再次變成了 1140px ,但由於 .row 裡面有 padding-rightpadding-left 15px,所以:
  • 容器寬為 1140px
  • 內容寬為 1110px
.col {
  position: relative;
  flex-basis: 0;
  flex-grow: 1;
  max-width: 100%;
  width: 100%;
  min-height: 1px;
  padding-right: 15px;
  padding-left: 15px;
}
Imgur

.col 裡面的 div

.col 中我們建立一個 <h4> 標籤,由於 .col 帶有 padding-leftpadding-right 15px 的緣故,所以 <h4>
  • 容器寬:1140px
  • 內容寬:1110px
Imgur

綜合上述,所以呢?

綜觀上面對於 .container, .row.col 的瞭解,我們可以知道,當.containermax-width: 1140px 時,整個容器的寬會是 1140px,但實際上內容的寬只會是 1110px,這兩者間差的 30px 就是來自於 padding-left: 15pxpadding-right: 15px

客制化 .container 容器寬度(Custom Container)

從上面的說明可以瞭解到,一般切版的時候,設計師給的稿上通常標示的會是內容寬度,而非容器寬度,因此假設設計師標示的內容寬度希望是 980px 時,我們就可以回推這時候我們 .containermax-width 應該要是 980px + 30px = 1010px。
速記:容器寬度 = 內容寬度 + 30px
註:這種算法只適用在 padding-left 和 padding-right 是 15px 的情況,也就是沒有修改 gutter 間距的情況。gutter 的修改會在後面的篇幅提到。
因此,我們可以在 HTML 中的 .container 這個 class 後面新增一個客制化的 class-.container-custom-width
<!-- HTML -->
<div class="container custom-container-width">
  <div class="row">
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam, minima.</h4>
    </div>
  </div>
</div>
CSS 的部分就去修改原本 .containermax-width
/**
 * 期望的內容寬 + 30px ,才會是最後的容器寬(不改變間距寬度的情況下)
**/

.container.custom-container-width {
    max-width: 1010px;       // 最後內容寬會是 980px
}
顯示的結果如下,上面原本的 container,容器寬是 1140px,內容寬是 1100px;下面是修改後的 .custom-container-width,可以看到新的樣式,容器寬是 1010px,內容寬就會是設計給的 980px,而左右兩邊的 margin 則會自動根據螢幕裝置寬度調整:
Imgur

那麼欄間距(gutters)呢?

在看完基本的 container 結構後,來看一下欄之間的間距吧。
前面有看到不論在 .container, .row, .col 中常常出現 15px 這個數字,基本上 Bootstrap 就是利用 padding 和 margin 中的 15px 做到間距的效果。
我們只要在 .row 中使用多個 .col 時,各個欄位間會自動出現間距,HTML 結構像是這樣:
<!-- HTML -->
<div class="container">
  <div class="row">
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
  </div>
</div>
畫面會像這樣:
Imgur
可以看到每個 .col 都有 padding-left 和 padding-right 15px,這也就是 gutter 的來源,由於左右都有 padding 的緣故,所以欄位之間的間距會是 30px。
註:這種透過左右添加 padding 和 margin 達到 gutter 的效果,稱作 "gutter on outside",可以在 skectch 中找到這個選項,若想瞭解更多可以參考這篇 What is the purpose of having outside gutters on a responsive grid? @ StackExchange(謝謝卡斯伯大大 提供)。

.no-gutters

在 Bootstrap4 中提供了 .no-gutters 這個 class,可以讓我們把間距拿掉。從 Bootstrap 4 原始檔中可以看到 .no-gutters 的 CSS 如下:
.no-gutters {
  margin-right: 0;
  margin-left: 0;
}

.no-gutters > .col,
.no-gutters > [class*="col-"] {
  padding-right: 0;
  padding-left: 0;
}
因此如果在 .row 上搭配 .no-gutters 則會把原本 .rowmargin-leftmargin-right-15px 拿掉,並且把 padding-leftpadding-right 都修為 0 ,因此原本欄和欄之間的間距會變為 0,畫面會像這樣:
Imgur
  • 容器寬(.container)為 1140px
  • 內容全寬為 1110px
  • .col間不在有間距存在

客制化欄間距(Custom Gutters)

知道欄間距的作法是透過 padding 和 margin 之後就可以客制化我們自己想要的間距大小,舉例來說,現在設計師希望欄和欄之間的間距不要是 30px 而是 20px 這時候我們就可以客制化調整我們的 gutter。
因為要同時修改 .container, .row, .col 所使用到的 margin 或 padding 的 px 值,所以我們把客制化 gutter 用的 class .custom-gutters 加在和 .container 同一層,HTML 結構長這樣:
<!-- HTML -->
<div class="container custom-gutters">
  <div class="row">
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
    <div class="col">
      <h4>div Lorem ipsum dolor sit amet.</h4>
    </div>
  </div>
</div>
CSS 的部分,則是去修改和間距寬度相關的像素值,並且利用 SCSS 建立一個變數名為 $custom-gutter-width
/* SCSS */
$custom-gutter-width: 20px;     // 將欄距改成 20px
.custom-gutters {
    &.container {
        padding-left: $custom-gutter-width / 2;
        padding-right: $custom-gutter-width / 2;
    }
    .row {
        margin-left: -($custom-gutter-width / 2);
        margin-right: -($custom-gutter-width / 2);
    }
    .col {
        padding-left: $custom-gutter-width / 2;
        padding-right: $custom-gutter-width / 2;
    }
}
從畫面中可以看到,.col 的 padding 變成 10px,因此欄和欄之間的間距變成 10 + 10 = 20px,而且因為沒有去改變 .container 的 max-width,所以整個容器寬還是一樣是預設的 1140px:
Imgur
要留意的是,當我們把間距改成 20px 時,表示 .col 左右兩邊各會有 10px 的 padding,因此我們的內容寬實際上會是 .col 寬度在少 20px:
Imgur

客制化 Bootstrap 變數

上面的作法主要是用在:
  1. 直接使用 Bootstrap 4 下載的 bootstrap.css 檔案,沒有辦法透過編譯器重新編譯 SCSS 檔案時。
  2. 只要套用在某些頁面,不是整個網頁都要改變容器寬度或欄間距時。
也就是說,如果你可以重新透過 SCSS 編譯出新的 CSS 檔,而且要套用在整個網頁的情況下時,就可以不用使用上述的方法,而是可以透過客制化 Bootstrap 變數的方法來達成。
Bootstrap 的變數存放在 Bootstrap 資料夾中 ./scss/_variables.scss 這支檔案,裡面列了許多變數,像這裡提到的容器寬度和欄間距都可以在這裡找到。
/* ./scss/_variables.scss  */
// Grid containers
// Define the maximum width of `.container` for different screen sizes.

$container-max-widths: (
  sm: 540px,
  md: 720px,
  lg: 960px,
  xl: 1140px
) !default;

// Grid columns
// Set the number of columns and specify the width of the gutters.

$grid-columns: 12 !default;
$grid-gutter-width: 30px !default;
另外每個變數後面都有寫 !default,代表你只要在這支 SCSS 檔之前先宣告 $container-max-widths$grid-gutter-width 的值時,它就會覆蓋掉 Bootstrap 預設的變數值。
關於客制化 Bootstrap 變數的方法,可以參考官方網站-Customization Options 的說明。

參考

Grid @ Bootstrap4

2017年6月12日

[Vue] 在 Vue 中使用(ES6 import) Bootstrap 4 和 jQuery

由於 bootstrap4 需要依賴 jquery 和 tether 這兩個套件,因此在 webpack 的環境底下使用 bootstrap4 有一些需要留意的細節才能正常載入使用。
⚠️ 這裡使用 @vue/cli 版本為 4.0.5,不同版本的設定方式可能略有不同,須特別留意。

使用 Vue CLI 安裝 vue

# 安裝 Vue CLI,目前版本為 4.0.5
$ npm install -g @vue/cli

# 使用 Vue CLI 建立專案
$ vue create vue-sandbox
vue-cli

安裝 Bootstrap

# 安裝 Bootstrap,目前版本為 4.3.1
$ npm i bootstrap
Imgur

載入 Bootstrap CSS 檔

可以直接在 main.js 中引入 bootstrap 的 css 檔:
// ./src/main.js
import 'bootstrap/dist/css/bootstrap.css'
Imgur

試試看:使用 Bootstrap 的 Alert 元件

現在,先來試試看是否有成功載入 Bootstrap 的樣式。打開 ./src/components/HelloWorld.vue,在裡面放入 Bootstrap 中的 alerts 元件,像這樣:
<!-- ./src/components/HelloWorld.vue -->
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>

    <!-- 開始:Bootstrap alert -->
    <div class="container">
      <div class="alert alert-warning alert-dismissible fade show" role="alert">
        <strong>Holy guacamole!</strong> You should check in on some of those fields below.
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
    </div><!-- 結束:Bootstrap alert -->

    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>

    <!-- ... -->
  </div>
</template>
使用 npm run serve 就可以把專案執行起來。沒有問題的話,畫面應該會像這樣子,可以看到中間已經套用了 Bootstrap 的 Alert 樣式:
Imgur
但此時若點擊 Alert 組件的關閉按鈕時,該警告並不會消失。這是因為我們還沒載入和 Bootstrap 有關的 JavaScript 檔案。

安裝和 Bootstrap 有關的 JavaScript 檔

如果你只是要載入 Bootstrap 的樣式檔,基本上到上面那步就可以了。
但是如果你有需要使用到 bootstrap 的其他互動功能,那麼就需要在額外載入 jQuery, Popper.js 和 Bootstrap 的 js 檔。
因此,讓我們一併安裝 jQuery 和 Popper,js:
$ npm install --save jquery popper.js

載入 Bootstrap 的 JavaScript 檔

要使用 Bootstrap 的 JS 檔,一樣直接在 ./src/main.js 中載入 bootstrap 就可以了:
// ./src/main.js
import Vue from 'vue'
import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap'      // 在這裡載入 Bootstrap 的 JavaScript 檔

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')
此時當我們點擊 Alert 組件的關閉按鈕時,該警告就會消失:
Imgur

載入 jQuery 使用

在上面的例子中,只要載入 Bootstrap 的 JavaScript 檔案後,它會自動去找到相依的 jQuery 套件,因此並不需要額外載入 jQuery 就可以使用。
但有些時候,Bootstrap 的有些互動行為是需要先透過 jQuery 來初始化的,例如 Tooltip 組件。Tooltip 組件在使用前需要針對想要產生 Tooltip 的元素使用 jQuery 來初始化它:
$(function () {
  $('[data-toggle="tooltip"]').tooltip()
})
這時候我們就會需要使用到 jQuery 提供的 $。要怎麼在 Vue 專案中取用到 jQuery 的 $ 呢?這時候我們會需要對 Vue 或者說是 Webpack 進行一些設定。

透過 vue.config.js 設定 webpack

在 Vue 專案中要進行 webpack 的設定,需要在根目錄中新增一支名為 vue.config.js 的檔案(放在和 package.json 同一層):
// 新增一隻名為 vue.config.js 的檔案在專案的根目錄

const webpack = require('webpack');

module.exports = {
  configureWebpack: {
    plugins: [
      new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'windows.jQuery': 'jquery',
      }),
    ],
  },
};
設定好了之後,在 Vue 專案中,就可以在需要使用 jQuery 的地方匯入 $ 就可以了:
import $ from 'jquery';

試試看:使用 Bootstrap 的 Tooltip 元件

現在讓我們用 Bootstrap Tooltip 元件來測試一下。先在 ./src/components/HelloWord.vue 中加入 Bootstrap 的 Tooltip 元件:
<!-- ./src/components/HelloWorld.vue -->
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>

    <div class="container">
      <!-- Bootstrap Alert -->
      <div class="alert alert-warning alert-dismissible fade show" role="alert">
        <strong>Holy guacamole!</strong> You should check in on some of those fields below.
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div> <!-- /Bootstrap Alert -->

      <!-- Bootstrap Tooltip -->
      <button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
        Tooltip on top
      </button> <!-- /Bootstrap Tooltip -->
    </div>

    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>

    <!-- ... -->
  </div>
</template>
這時候畫面會像這樣,但實際上滑鼠移過去並不會有任何效果:
Imgur
要達到滑鼠移過去有效果的話,需要載入 jQuery 並初始化它。因此我們可以在 ./src/components/HelloWorld.vue<script></script> 內去載入 jQuery 並組件 mounted 之後初始化它,像是這樣:
<!-- ./src/components/HelloWorld.vue -->
<template>
  <!-- ... -->
</template>

<script>
import $ from "jquery";    // STEP 1:載入 jQuery
export default {
  name: "HelloWorld",
  props: {
    msg: String
  },
  mounted() {
    // STEP 2:在 mounted 時初始化 tooltip
    $(function() {
      $('[data-toggle="tooltip"]').tooltip();
    });
  }
};
</script>
完成後,當滑鼠移過去時,就會出現 Tooltip 的提示文字:
Imgur
如此就可以繼續開心的使用 Bootstrap 啦!

完整程式碼

完整程式碼可在 vue-import-bootstrap4 @ github 檢視。

額外補充(將 jQuery 載入到全域環境)

如果我們只是使用 import 'jquery' 這種作法,是無法在全域環境(window)下使用 jQuery(這裡抓到的 $ 是 chrome 中內建的選擇器):
img
因此如果我們希望在全域環境下也可以使用 jQuery,我們可以使用下面這樣的寫法:
// ./src/main.js
import Vue from 'vue'
import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap'

// 讓瀏覽器的全域環境可以使用到 $
import jQuery from 'jquery'
window.$ = window.jQuery = jQuery
img

參考資料

2017年6月10日

[學習筆記] Bootstrap4 Grid System


在 Bootstrap4 的 Layout 使用的是 CSS flexbox 來達到排版的效果,因此建議可以先瞭解 flexbox 屬性的,flex-containerflex-items 的意義,將能夠更快理解 Bootstrap4。
以下內容整理自 Bootstrap 官方網站 Grid System。羅列我認為幾個比較重要的概念,如果時間允許的話,建議還是閱讀官方文件。

2015年4月18日