者|顏海鏡
編輯|覃云
出處丨前端之巔
本文已獲作者授權,轉載來源:
https://segmentfault.com/a/1190000016389031
劃重點,這是一道面試必考題,很多面試官都喜歡問這個問題,我就被問過好幾次了。
要實現上圖的效果看似很簡單,實則暗藏玄機,本文總結了一下 CSS 實現水平垂直居中的方式大概有下面這些,本文將逐一介紹一下,我將本文整理成了一個 github 倉庫在:https://github.com/yanhaijing/vertical-center
歡迎大家 star。
僅居中元素定寬高適用:
居中元素不定寬高:
為了實現上面的效果先來做些準備工作,假設 HTML 代碼如下,總共兩個元素,父元素和子元素:
<div class="wp"> <div class="box size">123123</div> </div>
wp 是父元素的類名,box 是子元素的類名,因為有定寬和不定寬的區別,size 用來表示指定寬度,下面是所有效果都要用到的公共代碼,主要是設置顏色和寬高。
注意:后面不在重復這段公共代碼,只會給出相應提示。
/* 公共代碼 */ .wp { border: 1px solid red; width: 300px; height: 300px; } .box { background: green; } .box.size{ width: 100px; height: 100px; } /* 公共代碼 */
絕對定位的百分比是相對于父元素的寬高,通過這個特性可以讓子元素的居中顯示,但絕對定位是基于子元素的左上角,期望的效果是子元素的中心居中顯示。
為了修正這個問題,可以借助外邊距的負值,負的外邊距可以讓元素向相反方向定位,通過指定子元素的外邊距為子元素寬度一半的負值,就可以讓子元素居中了,css 代碼如下。
/* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { position: relative; } .box { position: absolute;; top: 50%; left: 50%; margin-left: -50px; margin-top: -50px; }
這是我比較常用的方式,這種方式比較好理解,兼容性也很好,缺點是需要知道子元素的寬高。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/absolute1.html
這種方式也要求居中元素的寬高必須固定,HTML 代碼如下:
<div class="wp"> <div class="box size">123123</div> </div>
這種方式通過設置各個方向的距離都是 0,此時再講 margin 設為 auto,就可以在各個方向上居中了。
/* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { position: relative; } .box { position: absolute;; top: 0; left: 0; right: 0; bottom: 0; margin: auto; }
這種方法兼容性也很好,缺點是需要知道子元素的寬高。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/absolute2.html
這種方式也要求居中元素的寬高必須固定,所以我們為 box 增加 size 類,HTML 代碼如下:
<div class="wp"> <div class="box size">123123</div> </div>
感謝 css3 帶來了計算屬性,既然 top 的百分比是基于元素的左上角,那么在減去寬度的一半就好了,代碼如下
/* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { position: relative; } .box { position: absolute;; top: calc(50% - 50px); left: calc(50% - 50px); }
這種方法兼容性依賴 calc 的兼容性,缺點是需要知道子元素的寬高。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/absolute3.html
還是絕對定位,但這個方法不需要子元素固定寬高,所以不再需要 size 類了,HTML 代碼如下:
<div class="wp"> <div class="box">123123</div> </div>
修復絕對定位的問題,還可以使用 css3 新增的 transform,transform 的 translate 屬性也可以設置百分比,其是相對于自身的寬和高,所以可以講 translate 設置為 -50%,就可以做到居中了,代碼如下:
/* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { position: relative; } .box { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
這種方法兼容性依賴 translate2d 的兼容性。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/absolute4.html
利用行內元素居中屬性也可以做到水平垂直居中,HTML 代碼如下:
<div class="wp"> <div class="box">123123</div> </div>
把 box 設置為行內元素,通過 text-align 就可以做到水平居中,但很多同學可能不知道通過通過 vertical-align 也可以在垂直方向做到居中,代碼如下:
/* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { line-height: 300px; text-align: center; font-size: 0px; } .box { font-size: 16px; display: inline-block; vertical-align: middle; line-height: initial; text-align: left; /* 修正文字 */ }
這種方法需要在子元素中將文字顯示重置為想要的效果。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/lineheight.html
很多同學一定和我一樣不知道 writing-mode 屬性,感謝 @張鑫旭老師的反饋,簡單來說 writing-mode 可以改變文字的顯示方向,比如可以通過 writing-mode 讓文字的顯示變為垂直方向。
<div class="div1">水平方向</div> <div class="div2">垂直方向</div> .div2 { writing-mode: vertical-lr; }
顯示效果如下:
水平方向 垂 直 方 向
更神奇的是所有水平方向上的 css 屬性,都會變為垂直方向上的屬性,比如 text-align,通過 writing-mode 和 text-align 就可以做到水平和垂直方向的居中了,只不過要稍微麻煩一點:
<div class="wp"> <div class="wp-inner"> <div class="box">123123</div> </div> </div> /* 此處引用上面的公共代碼 */ /* 此處引用上面的公共代碼 */ /* 定位代碼 */ .wp { writing-mode: vertical-lr; text-align: center; } .wp-inner { writing-mode: horizontal-tb; display: inline-block; text-align: center; width: 100%; } .box { display: inline-block; margin: auto; text-align: left; }
這種方法實現起來和理解起來都稍微有些復雜。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/writing-mode.html
曾經 table 被用來做頁面布局,現在沒人這么做了,但 table 也能夠實現水平垂直居中,但是會增加很多冗余代碼:
<table> <tbody> <tr> <td class="wp"> <div class="box">123123</div> </td> </tr> </tbody> </table>
tabel 單元格中的內容天然就是垂直居中的,只要添加一個水平居中屬性就好了。
.wp { text-align: center; } .box { display: inline-block; }
這種方法就是代碼太冗余,而且也不是 table 的正確用法。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/table.html
css 新增的 table 屬性,可以讓我們把普通元素,變為 table 元素的現實效果,通過這個特性也可以實現水平垂直居中。
<div class="wp"> <div class="box">123123</div> </div>
下面通過 css 屬性,可以讓 div 顯示的和 table 一樣:
.wp { display: table-cell; text-align: center; vertical-align: middle; } .box { display: inline-block; }
這種方法和 table 一樣的原理,但卻沒有那么多冗余代碼,兼容性也還不錯。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/css-table.html
flex 作為現代的布局方案,顛覆了過去的經驗,只需幾行代碼就可以優雅的做到水平垂直居中。
<div class="wp"> <div class="box">123123</div> </div> .wp { display: flex; justify-content: center; align-items: center; }
目前在移動端已經完全可以使用 flex 了,PC 端需要看自己業務的兼容性情況。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/flex.html
感謝 @一絲姐 反饋的這個方案,css 新出的網格布局,由于兼容性不太好,一直沒太關注,通過 grid 也可以實現水平垂直居中。
<div class="wp"> <div class="box">123123</div> </div> .wp { display: grid; } .box { align-self: center; justify-self: center; }
代碼量也很少,但兼容性不如 flex,不推薦使用。
點擊查看完整 DEMO:
http://yanhaijing.com/vertical-center/grid.html
下面對比下各個方式的優缺點,肯定又雙叒叕該有同學說回字的寫法了,簡單總結下:
小貼士:關于 flex 的兼容性決方案,請看這里:
https://yanhaijing.com/css/2016/08/21/flex-practice-on-mobile/
最近發現很多同學都對 css 不夠重視,這其實是不正確的,比如下面的這么簡單的問題都有那么多同學不會,我也是很無語:
<div class="red blue">123</div> <div class="blue red">123</div> .red { color: red } .blue { color: blue }
問兩個 div 的顏色分別是什么,竟然只有 40% 的同學能夠答對,這 40% 中還有很多同學不知道為什么,希望這些同學好好補習下 CSS 基礎。
曉程序員,專注微信小程序開發的程序員!
前言:近期小程序項目中用到了滾動條功能,官方文檔中提供兩種方式。即wx.pageScrollTo滾動到page頁面的指定位置,<scroll-view>組件可以設置scroll-top或者scroll-left的值,今天探討一下使用哪種方式更合適。
1、wx.pageScrollTo
官方文檔地址:https://mp.weixin.qq.com/debug/wxadoc/dev/api/scroll.html
示例代碼:
wx.pageScrollTo({ scrollTop: 0 })
使用此方式,你需要知道以下幾點:
1、小程序基礎庫1.4.0之前不支持此方法,這點兒比較坑
2、小程序中雙擊頂部的textbar,會默認回到頂部
3、能夠觸發page的上拉(ReachBottom)和下拉(PullDownRefresh)事件
4、當頁面中有使用position:fixed布局時,彈出鍵盤時,fixed布局部分會閃屏
2、<scroll-view>
小程序中另一種實現滾動條的方式,是使用scroll-view組件。官方文檔:https://mp.weixin.qq.com/debug/wxadoc/dev/component/scroll-view.html
詳細的參數,請仔細查看官方文檔~
示例代碼:
<scroll-view class="scroll-view" scroll-y style="height: 500px;" scroll-top="{{scrollTop}}"> <view id="green" class="bc_green"></view> <view id="red" class="bc_red"></view> <view id="yellow" class="bc_yellow"></view> <view id="blue" class="bc_blue"></view> </scroll-view>
使scroll-view組件方式,你需要知道以下幾點:
1、縱向滾動(scroll-y)時,必須設置height值,并且不能使用css中的calc來計算,scroll-top值才會生效
2、小程序中雙擊頂部的textbar,無法回到頂部
3、無法觸發page的上拉(ReachBottom)和下拉(PullDownRefresh)事件
4、當頁面中position:fixed布局不受影響
往期回顧
1.微信小程序具備哪些API能力,你都清楚嘛?
2.小程序中tabBar的使用
3.小程序中picker的使用|日期、時間、省市區聯動都可以用它實現
4.swiper組件添加左右箭頭
5.如何跳出小程序五級頁面的限制
知曉程序員,一個專注于微信小程序開發的程序員~
如果對小程序技術感興趣,歡迎關注知曉程序員哦,歡迎討論問題 & 一起探討小程序人生~~
說明:
=====
1.1 Brython(Browser Python)是在瀏覽器中運行Python 3的一個實現。
1.2 Brython 設計用于替換網頁上的 JavaScript 腳本語言,它使用 Python 來編寫腳本,并直接在網頁上執行。
1.3 Brython 通過一套 JavaScript 庫對 Python 3 中的全部關鍵字以及大多數內置插件進行模擬,從而實現了將 Python 3 版本作為客戶端 Web 編程方案的目標。
1.4 Brython支持幾乎所有的python語法??梢赃M行控制臺編程,不支持高級編程(如,網絡編程等)。
1.5 Brython支持turtle繪圖庫,可以進行圖像繪制。Brython會把繪圖程序轉換成svg格式的動畫。
2 準備:
=====
2.1 傳送門:
https://github.com/brython-dev/brython
2.2 環境:
華為筆記本電腦、深度deepin-linux操作系統、谷歌瀏覽器、python3.8和微軟vscode編輯器。
2.3 安裝:
pip install brython
#本機安裝
sudo pip3.8 install -i https://mirrors.aliyun.com/pypi/simple brython
2.4 需要一定的html基礎知識,不過代碼中我已經注釋。
3 Hello=你好:
==========
3.1 代碼:1-Hello.html
<!DOCTYPE html>
<html>
<head>
<title>Hello=你好</title>
<meta charset="utf-8">
<!--本地引用-->
<!--script type="text/javascript" src="./brython.js"></script-->
<!--在線聯網引用-->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.7/brython.min.js"></script>
</head>
<!--調用brython;注意onload,有時候onLoad也可以,但是建議小寫-->
<!--括號內的數字,可以為空,為1-->
<body onload="brython(2)">
<script type="text/python">
#下面的代碼書寫是python格式,不是JavaScript=js格式
#注意需要導出document文件和alert警示彈出框
from browser import document, alert
#定義函數
def echo(ev):
#彈出警示框
alert("Hello=你好 {} !".format(document["zone"].value))
#文件test就是id綁定,同時綁定按鈕click與函數echo
document["test"].bind("click", echo)
</script>
<p>Your name is : <input id="zone" autocomplete="off">
<button id="test">click=點擊 !</button>
</body>
</html>
3.2 操作和效果圖:
4 簡易計算器=calculator:
==================
4.1 代碼:2-calculator.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.7/brython.min.js">
</script>
<!--設置樣式css-->
<style>
*{
font-family: sans-serif;
font-weight: normal;
font-size: 1.1em;
}
td{
background-color: #ccc;
padding: 10px 30px 10px 30px;
border-radius: 0.2em;
text-align: center;
cursor: default;
}
#result{
border-color: #000;
border-width: 1px;
border-style: solid;
padding: 10px 30px 10px 30px;
text-align: right;
}
</style>
</head>
<body onload="brython()">
<script type="text/python">
#導出模塊
from browser import document, html
#調用html函數
calc = html.TABLE()
calc <= html.TR(html.TH(html.DIV("0", id="result"), colspan=3) +
html.TD("C"))
lines = ["789/", "456*", "123-", "0.=+"]
calc <= (html.TR(html.TD(x) for x in line) for line in lines)
document <= calc
#結果放在文件idresult處顯示
result = document["result"]
#定義運算函數
def action(event):
element = event.target
value = element.text
if value not in "=C":
if result.text in ["0", "error"]:
result.text = value
else:
result.text = result.text + value
elif value == "C":
result.text = "0"
elif value == "=":
try:
x = eval(result.text)
result.text = x
except:
result.text = "error"
for button in document.select("td"):
button.bind("click", action)
</script>
</body>
</html>
4.2 操作和效果圖:
5 turtle繪圖:
==========
5.1 代碼:3-turtle.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<!--本地引用文件-->
<!--script type="text/javascript" src="./brython.js"></script-->
<!--script type="text/javascript" src="./brython_stdlib.js"></script-->
<!--在線聯網引用文件-->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython_stdlib.js"></script>
<script id="python_script" type="text/python">
import sys
import traceback
from browser import document, timer
FIRST_TIME = True
def inform(*args):
document["status-info"].html = "".join(args)
def _write(*args):
document["turtle-print-output"].html += "".join(args)
def __write(*args):
document["turtle-print-output"].html += '<span class="error">' + "".join(args) + "</span>"
sys.stdout.write = _write
sys.stderr.write = __write
def clear_print():
document["turtle-print-output"].html = ""
def run_code(ev):
global FIRST_TIME
if FIRST_TIME:
FIRST_TIME = False
inform("Importing turtle module for the first time and processing; please wait")
else:
inform("Processing")
document["run"].class_name = "btn-disabled"
# delay to allow updated DOM with above text to be shown.
timer.set_timeout(exec_code, 1)
document["run"].bind("click", run_code)
def exec_code():
_code= document["source"].text
try:
exec(_code)
except:
try:
traceback.print_exc()
except:
print("could not print traceback")
document["clear"].class_name = "btn-enabled"
document["replay-scene"].class_name = "btn-enabled"
inform("")
def delayed_clear():
from turtle import restart
restart()
inform("")
document["run"].class_name = "btn-enabled"
document["replay-scene"].class_name = "btn-disabled"
document["clear"].class_name = "btn-disabled"
clear_print()
def clear(ev):
global FIRST_TIME
if FIRST_TIME:
FIRST_TIME = False
inform("Importing turtle module for the first time and processing; please wait")
document["run"].class_name = "btn-disabled"
# delay to allow updated DOM with above text to be shown.
timer.set_timeout(delayed_clear, 1)
document["clear"].bind("click", clear)
def replay(ev):
# importing turtle earlier slows down the loading
# of this page
from turtle import replay_scene
replay_scene()
document["replay-scene"].bind("click", replay)
def copy_content(ev):
choice = document["demo_selector"].value
document["source"].text = document['demo'+ str(choice)].text
document["info"].html = document['info'+ str(choice)].html
clear(ev)
document["demo_selector"].bind("change", copy_content)
# Start with first demo
document["source"].text = document["demo1"].text
document["info"].html = document["info1"].html
</script>
<style>
h1, h2, h3, h4 {
color: blue;
}
pre {
max-width: 800px;
overflow: auto;
word-break: normal !important;
word-wrap: normal !important;
white-space: pre !important;
font-weight: bold;
}
pre#source {
border: 1px solid blue;
background-color:antiquewhite;
}
pre#turtle-docstring {
background-color: white;
max-width: 800px;
}
hr {
clear: both;
}
#info {
max-width: 800px;
border: 1px dotted black;
}
pre#turtle-print-output {
background-color: black;
color: yellow;
font-weight: bolder;
min-height: 50px;
height: auto;
max-height: 200px;
}
button {
margin: 20px;
padding: 10px;
}
#status-info {
color: darkred;
font-weight: bolder;
}
.error, .not-implemented {
color: red;
}
.btn-enabled {
color: black;
background-color: #c0c0c0;
}
.btn-disabled {
cursor: not-allowed;
pointer-events: none;
color: #c0c0c0;
background-color: #ffffff;
}
</style>
</head>
<body onload="brython(1)">
<h1>Turtle demo</h1>
<p>本來有許多下拉選擇項目,我剔除掉,只留下一個用來展示。
<select id="demo_selector" autocomplete="off">
<option value="1">Square with default turtle</option>
</select>
<br>
往下拉,可以看到代碼和畫圖過程。
</p>
<div id="info"></div>
<p><button id="run" class="btn-enabled">Run</button> <span id="status-info"></span>
<button id="clear" class="btn-disabled">Clear</button>
<button id="replay-scene" class="btn-disabled">Replay scene</button></p>
<pre id="turtle-print-output"></pre>
<pre id="source" style="float:left" contenteditable="true">
</pre>
<div id="turtle-div" style="float:left;border:1px solid green; margin-left:50px;"> </div>
<div id='info1' style='display:none'>
<h2>Simple demo</h2>
<p>When you click on <b>Run</b>, 開始運行代碼.</p>
<p>When you click on <b>Clear</b>, 開始清除代碼.</p>
<p>When you click on <b>Replay scene</b>, 重新加載屏幕.</p>
</div>
<div id='demo1' style="display:none">
#這個模塊導出是本特色
from browser import document
import turtle
#這個設置也是與html聯動
turtle.set_defaults(
turtle_canvas_wrapper = document['turtle-div']
)
#其他設置與python代碼無差別
t = turtle.Turtle()
t.width(5)
for c in ['red', '#00ff00', '#fa0', 'rgb(0,0,200)']:
t.color(c)
t.forward(100)
t.left(90)
t.penup()
t.goto(-30, -100)
t.dot(40, 'rgba(255, 0, 0, 0.5')
t.goto(30, -100)
t.dot(40, 'rgba(0, 255, 0, 0.5')
t.goto(0, -70)
t.dot(40, 'rgba(0, 0, 255, 0.5')
t.goto(0, 125)
t.color('purple')
t.write("I love Brython!", font=("Arial", 20, "normal"))
turtle.done()
</div>
</body>
</html>
5.2 操作和效果圖:
6 highcharts:
==========
6.1 文件結構:
6.2 代碼省略:太多了
6.3 操作和效果圖:換一種操作方式
===完美===
===自己整理并分享出來===
喜歡的就點贊、關注、評論、轉發和收藏。經典。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。