1. 程式人生 > >css flex佈局iOS8相容性問題

css flex佈局iOS8相容性問題

css flex佈局iOS8相容性問題,大多數情況下都能夠通過相容性寫法解決,比如:

div {
  display: -webkit-flex;
  display: flex;
  -webkit-flex: 1;
  flex: 1;
  flex-direction: row;
  -webkit-flex-direction: row;
}

如果以上相容性寫法還不能解決問題,那就要看看是不是webpack等自動化構建工具打包的時候導致部分css丟失。可以通過檢視打包後的檔案檢視css內容是否丟失。如果發現是webpack打包導致css部分內容丟失,可以試試下面的解決方法,我這邊通過下面的方法能夠解決問題。

檢查build目錄下的utils.js 的cssloader是否有minimize: true選項,如下:

const cssLoader = {
  loader: 'css-loader',
  options: {
    sourceMap: options.sourceMap,
    minimize: true
  }
}

檢查webpack.prod.conf.js是否用到OptimizeCSSPlugin外掛,如果有,則去掉,如下:

// new OptimizeCSSPlugin({
//   cssProcessorOptions: $sourceMap
//   ? { safe: true, map: { inline: false } }
//   : { safe: true }
// })

在專案根目錄下找到.postcssrc.js檔案,將該檔案內容替換為下面所示:

module.exports = {
  "plugins": {
    // to edit target browsers: use "browserslist" field in package.json
    "postcss-import": {},
    "autoprefixer": {
      browsers: [
        "last 10 versions",
        "ie >= 6",
        "ie_mob >= 6",
        "ff >= 10",
        "chrome >= 14",
        "safari >= 3",
        "ios >= 4",
        "android >= 4.0"
      ]
    }
  }
}

上面介紹的方法,主要針對的是webpack打包的時候,由於css外掛優化導致部分css內容丟失的解決方法。

這裡介紹個小技巧,在本地執行的頁面,複製該頁面的URL,如:http://127.0.0.1:8881/#/test,然後開啟草料二維碼,根據url生成二維碼,用真機掃描二維碼,如果真機上掃出來的頁面與本地的一致,說明真機瀏覽器是支援這些css的。

下面主要總結一下只在iOS8上發現(目前只在iOS8上發現,其他瀏覽器還沒發現問題)的一些比較坑的佈局問題。

1.元素設定flex:1後,子元素height: 100%失效的問題。

 <div id="container">
    <div id="div1">
      <div style="height: 100%; background-color: green;color: white">11111</div>
    </div>
    <div id="div2">
      <div style="height: 100%;color:white;background-color: blue">22222</div>
    </div>
    <div id="div3">3</div>
    <div id="div4">4</div>
</div>
<style>
  #container {
    display: flex;
    height: 100%;
  }
  #div1 {
    flex: 1;
    background-color:yellow;
  }
  #div2 {
    flex: 1;
    background-color: red;
  }
  #div3 {
    flex: 1;
    background-color:yellow;
  }
  #div4 {
    flex: 1;
    background-color: red;
  }
</style>

如上,理論上,div1,div2,div3,div4會平分父容器container,並且div1會被背景色為綠色的子元素撐滿,div2會被背景色為藍色的子元素撐滿。實際上,iOS8上的顯示效果如圖1所示。可見div1,div2的子元素的height: 100%失效了。解決方法可以通過給div1,div2設定position:relative,然後設定div1,div2的子元素position: absolute;height: 100%;width: 100%。問題即可解決。如圖2。

 <div id="container">
    <div id="div1">
      <div style="height: 100%; background-color: green;color: white">11111</div>
    </div>
    <div id="div2">
      <div style="height: 100%;color:white;background-color: blue">22222</div>
    </div>
    <div id="div3">3</div>
    <div id="div4">4</div>
</div>
<style>
  #container {
    display: flex;
    height: 100%;
  }
  #div1 {
    posititon: relative;
    flex: 1;
    background-color:yellow;
  }
  #div1 div {
    position: absolute;
    height: 100%;
    width: 100%;
  }
  #div2 {
    position: relative;
    flex: 1;
    background-color: red;
  }
  #div3 div {
    position: absolute;
    height:height;
    width: height;
  }
  #div3 {
    flex: 1;
    background-color:yellow;
  }
  #div4 {
    flex: 1;
    background-color: red;
  }
</style>

圖1 height:100%失效

圖2 解決height:100%失效的問題​​​​​​

2.一個奇怪的css失效問題,至今沒想明白原因。使用vue 的v-if指令切換元素的顯示,同時元素的css是通過子元素選擇器選擇時,元素的佈局失效。如下面程式碼所示:

<template>
  <div id="test">
    <div class="container">
      <div id="div1" v-if="!show">
        <div>左列</div>
        <div>右列</div>
      </div>
      <div id="div2" v-else>一列</div>
    </div>
    <div style="padding: 20px; text-align:center;background-color: red" @click="show=!show">切換</div>
  </div>
</template>
<style lang="less" scoped>
  .container {
    padding: 20px;
    & > div {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
  }
</style>
<script>
  export default {
    data() {
      return {
        show: false
      }
    }
  }
</script>

按照程式碼所寫,理論上,不管點選‘切換’按鈕多少次,div1的佈局永遠都是兩邊對齊,即包括‘左列’的塊在左邊,包含‘右列’的塊在右邊。然而在iOS8上,頁面第一次載入完成後,div1的佈局確實是兩邊對齊,當點選‘切換’按鈕後,div1的佈局就失效了,如下圖所示。目前只在iOS8發現這個問題。

圖1 頁面第一次載入完成時,div1兩邊對齊,佈局正常

圖2 點選‘切換’按鈕,div1隱藏,div2 顯示

圖3.點選‘切換’按鈕,div1顯示,div2隱藏,此時div1佈局異常

從圖3可以看出,但div1再次顯示時,div1的佈局不再是兩邊對齊(圖1所示)。iOS8出現這個bug的原因還沒想明白,但可以稍微修改一下程式碼,就能解決這個問題,如下所示,使用class代替子元素選擇器選擇div1的佈局:

<template>
  <div id="test">
    <div class="container">
      <div id="div1" class="row" v-if="!show">
        <div>左列</div>
        <div>右列</div>
      </div>
      <div id="div2" v-else>一列</div>
    </div>
    <div style="padding: 20px; text-align:center;background-color: red" @click="show=!show">切換</div>
  </div>
</template>
<style lang="less" scoped>
  .container {
    padding: 20px;
    .row {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
  }
</style>
<script>
  export default {
    data() {
      return {
        show: false
      }
    }
  }
</script>