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>