CSS學習摘要-定位例項
注:全文摘自MDN-CSS定位例項
列表訊息盒子
我們研究的第一個例子是一個經典的選項卡訊息框,你想用一塊小區域包括大量資訊時,一個非常常用的特徵。這包括含有大資訊量的應用,比如策略戰爭遊戲,比如從移動版的網頁,螢幕狹小、空間有限;比如你可能想要放置許多資訊的緊湊訊息框,不用就會充滿整個UI。我們簡單的例子完成後就會像下面這樣:
注意: 你能看完整的示例,可執行在 info-box.html (source code)。檢出它以理解你在本文章裡要建立什麼。
你可能會想:”為什麼不僅僅做獨立的選項卡為一個獨立的網頁,然後通過點選不同的標籤來在不同的頁面跳轉來達到這個效果?“這樣程式碼可能會簡單一些,是的。但是這樣每個獨立的”頁面“檢視將會實際上是一個新載入的網頁,跨檢視更難儲存資訊,並把這個特徵融入一個更大的UI設計。另外,所謂的”單頁應用“正在變得非常流行——尤其是移動網頁UI——因為把一切的服務放在一個單獨的檔案上可以減少HTTP請求的數量來瀏覽所有內容,從而提高效能。
注意: 一些網路開發者甚至更超前,每次只載入一頁的資訊,並且使用JavaScript諸如 XMLHttpRequest特徵動態改變資訊顯示。在你學習的此刻,然而,我們希望儘可能保持簡單。接下來有一些JavaScript,但是隻有一點。
在開始之前,我們需要你拷貝檔案到本地,當作起始的HTML檔案—— info-box-start.html. 儲存到你的計算機合適的位置,然後在你的編輯器裡開啟。讓我們看看包含在 body 裡的HTML程式碼:
<section class="info-box">
<ul>
<li><a href="#" class="active">Tab 1</a></li>
<li><a href="#">Tab 2</a></li>
<li><a href="#">Tab 3</a></li>
</ul>
<div class="panels">
<article class="active-panel">
<h2>The first tab</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. Vestibulum et orci scelerisque, vulputate tellus quis, lobortis dui. Vivamus varius libero at ipsum mattis efficitur ut nec nisl. Nullam eget tincidunt metus. Donec ultrices, urna maximus consequat aliquet, dui neque eleifend lorem, a auctor libero turpis at sem. Aliquam ut porttitor urna. Nulla facilisi.</p>
</article>
<article>
<h2>The second tab</h2>
<p>This tab hasn`t got any Lorem Ipsum in it. But the content isn`t very exciting all the same.</p>
</article>
<article>
<h2>The third tab</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque turpis nibh, porttitor nec venenatis eu, pulvinar in augue. And now an ordered list: how exciting!</p>
<ol>
<li>dui neque eleifend lorem, a auctor libero turpis at sem.</li>
<li>Aliquam ut porttitor urna.</li>
<li>Nulla facilisi</li>
</ol>
</article>
</div>
</section>
這樣我們已經得到了一個<section>
元素帶有類(class
)為 info-box
。此元素又包含一個 <ul>
和一個 <div>
。無序列表包含三個列表項,列表項有連結在內,實際上將成為用於點選後顯示內容皮膚的選項卡。 div
包含三個<article>
(<article>
元素表示文件、頁面、應用或網站中的獨立結構,其意在成為可獨立分配的或可複用的結構,如在釋出中,它可能是論壇帖子、雜誌或新聞文章、部落格、使用者提交的評論、互動式元件,或者其他獨立的內容專案。) 元素,構成對應於每個選項卡的內容皮膚。 每個皮膚包含一些示例內容。
這裡的思路是我們將樣式化選項卡看起來是一個標準的水平導航選單,使用絕對定位樣式化皮膚互相坐落其頂上。我們也給你一點JavaScript包含到你的頁面上,當選項卡被按下時,顯示對應的皮膚,並且樣式化選項卡本身。你不需要在這個階段瞭解JavaScript本身,但是你應該儘快學習一些基本的 JavaScript——你的使用者介面越複雜,越需要一些JavaScript來實現你渴望的功能。
一般設定
開始前,在<style>
開閉標籤之間新增下面的程式碼:
html {
font-family: sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
這只是一些一般設定,在我們頁面上設定了無襯線的字型、使用 box-sizing
模型,去掉 <body>
預設外邊距。
下一步,在你早先的CSS下面加入如下程式碼:
.info-box {
width: 450px;
height: 400px;
margin: 0 auto;
}
這對內容設定具體的高度和寬度、在螢幕居中使用老把戲 margin: 0 auto
。在早先的課程中我們建議儘可能不固定內容容器的高度。這個情況下是可以的,因為我們是在選項卡中固定的內容,如果每個標籤都有不同的高度,看起來也有些不和諧。
樣式化我們的選項卡
現在我們希望樣式化選項卡看上去像選項卡——基本,這些是一個水平的導航標籤,但不是點選之後載入不同的網頁,和我們之前在課程中見到的不同,相反,他們在同一頁面上顯示不同的皮膚。首先,在你的CSS底部新增下列規則,從無序列表中移除預設的padding-left
和margin-top
值:
.info-box ul {
padding-left: 0;
margin-top: 0;
}
注意: 我們正在使用後代選擇器,整個例子 .info-box
都位於鏈的開始——這樣頁面已經帶有其他內容時,我們可以插入這個特徵,不害怕與應用於頁面其他部分的樣式衝突。
接下來,我們將樣式化水平選項卡——列表項都要左浮動確保他們一行合起來,他們的list-style-type
被設定為 none
用以去除專案符號,寬度(width
)設定為 150px
以便於適應這個info-box。連結( <a>
)元素設定為display
inline-block,這樣他們將在一行顯示,仍然保持樣式可設定,他們會被樣式化合適的選項卡按鈕,通過一系列的其他屬性。
新增下列的CSS:
.info-box li {
float: left;
list-style-type: none;
width: 150px;
}
.info-box li a {
display: inline-block;
text-decoration: none;
width: 100%;
line-height: 3;
background-color: red;
color: black;
text-align: center;
}
最後,對於本節,我們將會在連結狀態上設定一些樣式。首先,我們要設定標籤的 :focus
和 :hover
狀態,讓他們在獲得焦點/滑鼠懸浮的時候看起來不同,給使用者提供一些視覺化反饋。其次,當某個選項卡的類( class
)出現 active
時,我們為其設定一條相同的樣式規則。我們將通過使用JavaScript來設定,當一個標籤被點選時。把這些CSS放置在你的其他樣式後面:
.info-box li a:focus, .info-box li a:hover {
background-color: #a60000;
color: white;
}
.info-box li a.active {
background-color: #a60000;
color: white;
}
樣式化皮膚
下一步工作是樣式化我們的皮膚,現在開始吧!
首先,新增下列的規則去樣式化 .panels
<div>
容器。我們簡單的設定一個固定的高度,確保皮膚包含在info-box裡面,position
relative
設定 <div>
為定位上下文,這樣你能然後相對自身放置定位子元素,而不是相對<html>
元素,最後我們清除(clear
)浮動,設定在上面CSS中,這樣避免影響佈局的剩餘部分。
.info-box .panels {
height: 352px;
position: relative;
clear: both;
}
在本節的最後,我們將對包含我們皮膚的單獨 <article>
元素設定樣式。我們新增的第一條規則就是絕對定位皮膚,讓他們都位於<div>
容器的左上角——這一部分對整個佈局特性是關鍵的,就像使皮膚互相位於頂部。規則設定皮膚為和容器同樣的高度,給內容一些內邊距,設定字型顏色(color
),和背景顏色(background-color
)。
我們將新增的第二條規則,對帶有類( class
)為( active-panel
)的皮膚,設定z-index
為 1,會讓他位於其他的皮膚之上(預設定位元素 z-index
的值是 0,會使預設元素位於下面)。同樣的,我們會在合適的時候用JavaScript 來新增這個類。
.info-box article {
position: absolute;
top: 0;
left: 0;
height: 352px;
padding: 10px;
color: white;
background-color: #a60000;
}
.info-box .active-panel {
z-index: 1;
}
新增我們的JavaScript
讓這些特性工作的最後一步是新增一些JavaScript。新增下列一塊程式碼,準確的寫在你的開始和結束的<script>
標籤之間(在接下來的HTML內容中你將會發現這些):
var tabs = document.querySelectorAll(`.info-box li a`);
var panels = document.querySelectorAll(`.info-box article`);
for(i = 0; i < tabs.length; i++) {
var tab = tabs[i];
setTabHandler(tab, i);
}
function setTabHandler(tab, tabPos) {
tab.onclick = function() {
for(i = 0; i < tabs.length; i++) {
if(tabs[i].getAttribute(`class`)) {
tabs[i].removeAttribute(`class`);
}
}
tab.setAttribute(`class`, `active`);
for(i = 0; i < panels.length; i++) {
if(panels[i].getAttribute(`class`)) {
panels[i].removeAttribute(`class`);
}
}
panels[tabPos].setAttribute(`class`, `active-panel`);
}
}
這些程式碼做了如下工作:
-
首先我們儲存所有的選項卡和所有的皮膚引用到兩個變數中,名為
tabs
和panels
,這樣此後我們可以容易地為它們做事。 -
然後我們使用
for
迴圈遍歷所有的選項卡,並且在每一個上執行叫做setTabHandler()
的函式,此函式建立當每個選項卡被點選時應該發生的功能。 執行時, 函式會被傳遞選項卡,和一個索引數i
指明選項卡在tabs
陣列中的位置。 -
在setTabHandler()函式中,這個標籤建立了一個onclick事件來處理點選,所以當標籤被點選的時候,接下來會發生:
-
一個for迴圈用來清除所有標籤當前存在的類。
-
當點選的時候在標籤上建立了一個active 類——從相關聯的元素中繼承了CSS的一些屬性,具有和panels的樣式相同的顏色,背景顏色。
-
一個for迴圈用於清除所有皮膚當前存在的類。
-
當標籤被點選的時候在和標籤相對應的皮膚上建立了一個active-panel 類——從相關聯的元素中繼承了CSS的一些屬性,使他的z-index屬性被設定為1,讓他能位於所有的皮膚的上面。
-
效果如下:
一個固定位置的列表訊息盒子
在我們的第二個例子中,我們將會採用我們的第一個例子——我們的訊息盒子——把她加到一個滿的網頁之中去。但是不僅僅是這樣——我們將固定她的位置,以便於他能待在瀏覽器視窗的同一個位置。當主要內容滾動時,這個訊息盒子將會待在螢幕的同一個位置。我們完工以後的例子長下面這樣:
注:你可以點選藍字 fixed-info-box.html (source code)預覽完成後的效果,看看哪些部分是你在這篇文章裡你要製作的。
在開始的時候,你可以使用第一部分中完成的例子,或者從我們的Github倉庫中info-box.html 拷貝info-box.html到本地。
新增HTML
首先,我們需要一些額外的內容在當前的主內容中。新增下列部分在你的body標籤之中,在已存在的部分之中前:
<section class="fake-content">
<h1>Fake content</h1>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
<p>This is fake content. Your main web page contents would probably go here.</p>
</section>
注:你可以隨意更改內容,替換為你想要內容。
更改存在的CSS
接下來我們需要對之前的Css進行一些小修改,讓訊息盒子放置和定位的好一些。刪除你的margin: 0 auto (不需要居中顯示),新增fixed定位;調整top 屬性把她粘在瀏覽器的視域。
.info-box {
width: 450px;
height: 400px;
position: fixed;
top: 0;
}
對主內容樣式設計
對於這個例子來說唯一剩下的事情就是給主內容提供一些樣式設計。新增下面的規則到你剩下的Css 的下面:
.fake-content {
background-color: #a60000;
color: white;
padding: 10px;
height: 2000px;
margin-left: 470px;
}
開始我們給這個內容和訊息盒子皮膚一樣的背景顏色,顏色,內邊距。然後給他一個大的margin-left使他移動到右邊,為訊息盒子在左邊騰出位置,以便於各個部分不重疊。
這標誌著第二個例子的結束;我們希望你能感到第三個例子,完全是因為興趣。
一個滑動隱藏的皮膚
最後一個我們在這裡介紹的例子是通過按圖示使皮膚滑動出現或者消失——就像前面提到的,這種場景在移動端的佈局很流行,因為移動端的螢幕很小,所以你不希望使用大部分介面來顯示一個有用的內容而是用訊息皮膚或者選單代替。
我們完工後的例子長這樣:
提示:你可以點選藍字hidden-info-panel.html (source code)預覽完成後的效果,仔細看看哪些部分是你在這篇文章裡你要製作的。
在一開始,老規矩在我們的Githib程式碼倉庫拷貝hideen-info-panel-start.html(原始碼)。
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Hidden info panel</title>
<style>
/* || Checkbox hack to control information box display */
label[for="toggle"] {
font-size: 3rem;
position: absolute;
top: 4px;
right: 5px;
z-index: 1;
cursor: pointer;
}
input[type="checkbox"] {
position: absolute;
top: -100px;
}
/* information box styling */
aside {
background-color: #a60000;
color: white;
width: 340px;
height: 100%;
padding: 0 20px;
position: fixed;
top: 0;
right: -370px;
transition: 0.6s all;
}
/* Second part of the checkbox hack — the checked state */
input[type=checkbox]:checked + aside {
right: 0px;
}
</style>
</head>
<body>
<label for="toggle">?</label>
<input type="checkbox" id="toggle">
<aside>
<h2>Information</h2>
<p>Some very important information about your app:</p>
<ol>
<li>It has a really cool slide-out information box.</li>
<li>This information box uses a combination of fixed positioning and a CSS transition for the smooth sliding.</li>
<li>It also uses a cool technique called the <a href="https://css-tricks.com/the-checkbox-hack/">checkbox hack</a>.</li>
<li>This allows you to create a nice "toggle on/toggle off" UI effect without using any JavaScript, which will work in IE9 and above (the smooth transition will work in IE10 and above.)</li>
</ol>
</aside>
</body>
</html>
這個例子並沒有用先前的例子,所以我們需要一個新的開始檔案。讓我們來仔細觀察一下這個HTML檔案:
<label for="toggle">❔</label>
<input type="checkbox" id="toggle">
<aside>
...
</aside>
//label
的 for屬性規定label屬性繫結到哪個表單元素。
開始,我們看到了一個label 元素和input元素——<label>
元素普遍用來聯絡文字標籤和表單,目的是能更好的理解表單(允許使用者檢視錶單元素的描述)。這裡通過for屬性繫結id到了<input>
標籤的checkbox元素。
提示:我們已經設定了一個特殊的問題標記特性到我們的HTML中,來當作我們的資訊圖示——這代表著這個按鈕將可以按下顯示或隱藏皮膚。
現在我們使用這些元素稍稍不同的目的——另一個<label>
標籤有副作用使你能通過點選checkbox的label標籤來選擇這個checkbox,就好像點選了這個checkbox自己一樣。這就會實現有名的checkbox hack 技術,可以提供無JS的方法來控制一個元素,通過一個按鈕的聯絡。我們將控制的元素使aside元素,通過其他兩個(為了簡潔起見,我們已將其內容從上述程式碼列表中刪除)。
在下面的部分我們將解釋這一切如何運作。
設定表單元素樣式
首先讓我們處理表單元素 – 在style標籤之間新增以下CSS:
label[for="toggle"] {
font-size: 3rem;
position: absolute;
top: 4px;
right: 5px;
z-index: 1;
cursor: pointer;
}
input[type="checkbox"] {
position: absolute;
top: -100px;
}
-
第一條label樣式的規則,我們有:
-
設定字型大小使圖示更美觀。
-
設定為絕對定位,使用top屬性和right屬性來讓他能很合適的位於右上角。
-
設定z-index屬性為1——因此當資訊皮膚被賦予樣式和顯示的時候,不會覆蓋我們的圖示;相反圖示依然會位於最上層能夠再次被按下來隱藏資訊平板。
-
使用cursor屬性來說改變滑鼠的指標,當滑鼠懸浮在圖示上面的時候變成一個手形指標(就像你看到的當懸浮在連結上一樣),作為一個額外的視覺化線索告訴使用者這個圖示可以做一些有趣的事情。
-
-
第二條規則是在實際的
<input>
checkbox元素上設定絕對定位屬性,並隱藏在頂部的上面,我們並不希望在我們的使用者介面裡看到她。
設定皮膚的樣式
現在是時候為實際的滑動皮膚設計風格了。在你的css底部新增下列規則:
aside {
background-color: #a60000;
color: white;
width: 340px;
height: 98%;
padding: 10px 1%;
position: fixed;
top: 0;
right: -370px;
transition: 0.6s all;
}
這裡有很多項——讓我們一點一點討論:
-
首先,我們在資訊盒子中設定了一些簡單的背景顏色和顏色。
-
然後,我們在皮膚上設定一個固定的寬度,讓她的高度充滿整個瀏覽器視窗的高度。
-
我們同樣包括一些內邊距來組成我們小於那個要的高度和寬度總體的值(如果我們沒有設定box-sizing:border-box來說的話是很必要的,正如這個例子)
-
然後,我們設定皮膚的定位為fixed,即使頁面的內容在滾動,也總是顯示在同一個位置。我們把設定top屬性讓視窗粘在頂部,然後設定預設情況下遠離螢幕,設定right屬性使其位於螢幕的右邊。
-
最後我們設定transition屬性,Transitions是一個有意思的特性,允許你在狀態改變的時候平滑的過渡,而不是粗暴的“變”或“還原”。在這個例子中我們嘗試在checkbox被選中時讓皮膚平滑的滑動到螢幕上。(或者換句話說,當問題標記圖示被點選以後——記住,點選
設定選擇後的狀態
這是最後的css新增——把這些放到你的css底部:
input[type=checkbox]:checked + aside {
right: 0px;
}
這裡的選擇器是複雜的——我們選擇<input>
元素鄰接的<aside>
元素,但是僅僅在他被選擇(請注意使用checked偽類來實現此目的),在這種情況下,我們將right屬性設定為0px,會造成皮膚再次出現在螢幕上(由於過渡屬性會平滑的出現)。再一次點選這個標籤會取消選中checkbox,皮膚將會跟著再一次消失。
所以你有它 ——一個相當巧妙的避免使用JavaScript來建立一個切換按鈕效果方式。 這將在IE9及以上版本中起作用(平滑過渡將在IE10及更高版本中起作用)。這種效果確實有一些問題 ——這是有點濫用表單元素(它們不是為了這個目的),並且在可訪問性方面效果不是很好 – 標籤在預設情況下不可聚焦,並且表單元素的非語義使用可能會導致螢幕朗讀器出現問題。 JavaScript和連結或按鈕可能更合適,但這樣的實驗仍然很有趣。
最後完成的程式碼如下:
(另外這裡我使用了?
來取代那個問號的圖示,效果是一樣的。)
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<title>Hidden info panel</title>
<style>
/* || Checkbox hack to control information box display */
label[for="toggle"] {
font-size: 3rem;
position: absolute;
top: 4px;
right: 5px;
z-index: 1;
cursor: pointer;
}
input[type="checkbox"] {
position: absolute;
top: -100px;
}
/* information box styling */
aside {
background-color: #a60000;
color: white;
width: 340px;
height: 98%;
padding: 10px 1%;
position: fixed;
top: 0;
right: -370px;
transition: 0.6s all;
}
/* Second part of the checkbox hack — the checked state */
input[type=checkbox]:checked + aside {
right: 0px;
}
</style>
</head>
<body>
<label for="toggle">?</label>
<input type="checkbox" id="toggle">
<aside>
<h2>Information</h2>
<p>Some very important information about your app:</p>
<ol>
<li>It has a really cool slide-out information box.</li>
<li>This information box uses a combination of fixed positioning and a CSS transition for the smooth sliding.</li>
<li>It also uses a cool technique called the <a href="https://css-tricks.com/the-checkbox-hack/">checkbox hack</a>.</li>
<li>This allows you to create a nice "toggle on/toggle off" UI effect without using any JavaScript, which will work in IE9 and above (the smooth transition will work in IE10 and above.)</li>
</ol>
</aside>
</body>
</html>
gif效果圖:
總結
這樣完成了我們對定位的關注——現在,你應該理解基本機制的工作原理,同樣理解了怎樣應用這些知識去構建一些有趣的使用者介面功能,不要由於你還未完全理解所有的知識而擔心——定位是一個相當高階的話題,你可以隨時讀這篇文章來幫助你的理解。下一個主題我們將轉向Flexbox。
【end】