Hôm nay chúng ta tiếp tục làm việc với CSS3, ở bài trước mình đã giới thiệu tới các bạn bộ thư viện CSS3 Library Animation với những hiệu ứng độc đáo mà CSS3 làm được, hôm nay mình sẽ hướng dẫn các bạn cách tạo một Accordion với CSS3.

Trước đây anh Demon Warlock đã có 2 bài hướng dẫn cách tạo Accordion với Jquery và các bạn có thể xem lại.

#STEP 1 – SETUP HTML

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title>Accordion with CSS3</title>
	<link rel="stylesheet" type="text/css" href="css/style.css" media="all">
	<link rel="stylesheet" type="text/css" href="css/reset.css" media="all">
</head>
<body>
	<div id="wrapper">
		<div class="container">
			<article id="accordion-content">
				<div>
					<input id="accordion-1" name="accordion" type="radio" checked />
					<label for="accordion-1">Home</label>
					<section class="tab">
						<p>Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
						</p>
					</section>
				</div>

				<div>
					<input id="accordion-2" name="accordion" type="radio"/>
					<label for="accordion-2">About us</label>
					<section class="tab">
						<p>Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
						</p>
					</section>
				</div>

				<div>
					<input id="accordion-3" name="accordion" type="radio"/>
					<label for="accordion-3">FAQs</label>
					<section class="tab">
						<p>Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
						</p>
					</section>
				</div>

				<div>
					<input id="accordion-4" name="accordion" type="radio"/>
					<label for="accordion-4">Contact us</label>
					<section class="tab">
						<p>Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
						</p>
					</section>
				</div>
		</article><!-- End #accordion-content -->
		</div><!-- End .container -->

		<a href="index2.php" class="demo">Demo 2</a>
	</div><!-- End #wrapper -->
</body>
</html>

Select Radio là loại select chỉ có thể chọn 1 cái duy nhất và select checkbox là loại select có thể chọn nhiều cái cùng một lúc và có thể click lại để bỏ chọn, trong bài này mình sẽ sử dụng chúng để select đến từng tab trong Accordion.

<input id="accordion-1" name="accordion" type="radio" checked />
<input id="accordion-1" name="accordion" type="checkbox" checked />

Tất cả thẻ input của mình có name là accordion, mỗi thẻ input có một id khác nhau để khi người dùng click đến tab nào thì thông tin của tab đó sẽ hiển thị ra và id của thẻ input này cũng chính là cầu nối giữa thẻ input và thẻ label.

Demo thứ 1 mình làm type là radio có nghĩa là chỉ xem được một tab và khi mở tab khác thì tab này sẽ đóng lại.

Demo thứ 2 mình làm type là checkbox có nghĩa là bạn có thể mở được nhiều tab cùng 1 lúc và bạn có thể click lại tab đó để đóng nó lại.

Thuộc tính “Checked” ở trên có nghĩa là khi người dùng vào lần đầu tiên thì nó sẽ mở cái tab đó, phần nội dung chính của mình sẽ nằm trong cặp thẻ section. Nếu các bạn áp dụng vào một trang web nào đó thì bạn cần nên làm đúng như cấu trúc trong đoạn HTML trên thì nó mới hoạt động được và bạn chỉ có thể thay thế phần nội dung của mình trong thẻ section và style CSS lại cho nó.

Nhắc thêm 1 xíu cho bạn nào áp dụng cái này trong PHP và kéo dữ liệu trong MYSQL ra.

Nếu bạn dùng vòng lặp while để lấy dữ liệu từ MYSQL ra, khi xuất cái đoạn code này trong vòng lặp, chắc có một số bạn sẽ hỏi là trong id của thẻ input và cái for trong thẻ label nó có các số đấy thì mình sẽ xử lý nó như thế nào cho đúng với cấu trúc HTML ban đầu thì các bạn làm như sau.

<?php 

     $db = mysqli_connect("localhost","root","","db");
     $i = 1;
     $query = "SELECT * FROM table_noidung";
     $result = mysqli_query($db,$query);
	while($row=mysqli_fetch_array($result)) {
	    $content = $row['content'];
            $title = $row['title'];
?>
     <div>
          <input id="accordion-<?php echo $i; ?>" name="accordion" type="radio" <?php if($i==1) echo 'checked';?> />
	  <label for="accordion-<?php echo $i; ?>"><?php echo $title; ?></label>
		<section class="tab">
		   <p>
			<?php echo $content; ?>
		   </p>
		</section>
     </div>

<?php 
	$i++;
} // End while

?>

Đoạn trên mình sẽ khai báo một biến $i=1, sau đó các bạn dùng vòng lặp while để lấy dữ liệu, khi bạn echo đoạn HTML ra thì cái số ở thẻ input và label các bạn thay biến $i vào đó. Biến $id sẽ chạy từ 1 là cho cái input đầu tiên và cứ mỗi lần lặp nó sẽ tăng $i lên 1 …Nếu $i =1 thì mình sẽ cho nó checked.

#STEP 2 – SETUP CSS

 
@font-face {
    font-family: 'BebasNeueRegular';
    src: url('../fonts/BebasNeue-webfont.eot');
    src: url('../fonts/BebasNeue-webfont.eot?#iefix') format('embedded-opentype'),
         url('../fonts/BebasNeue-webfont.woff') format('woff'),
         url('../fonts/BebasNeue-webfont.ttf') format('truetype'),
         url('../fonts/BebasNeue-webfont.svg#BebasNeueRegular') format('svg');
    font-weight: normal;
    font-style: normal;
}

body {
	font-family: Cambria, Palatino, "Palatino Linotype", "Palatino LT STD", Georgia, serif;
}

a{
	color: #333;
	text-decoration: none;
}

a.demo {
	text-align: center;
	border: 1px solid #d4d4d4;
	background: #C6E1EC;
	padding: 5px 10px;
	margin-top: 20px;
	margin-left: 45%;
}

#wrapper {
	width: 1000px;
	margin: 0 auto;
}

.container {
	width: 450px;
	margin: 10px auto 30px auto;
	text-align: left;
}

#accordion-content label{
	font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif;
	padding: 5px 20px;
	position: relative;
	z-index: 20;
	display: block;
	height: 30px;
	cursor: pointer;
	color: #777;
	text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
	line-height: 33px;
	font-size: 19px;
	background: #ffffff;
	background: -moz-linear-gradient(top, #ffffff 1%, #eaeaea 100%);
	background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eaeaea));
	background: -webkit-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
	background: -o-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
	background: -ms-linear-gradient(top, #ffffff 1%,#eaeaea 100%);
	background: linear-gradient(top, #ffffff 1%,#eaeaea 100%);
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eaeaea',GradientType=0 );
	box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3), 1px 0px 0px 0px rgba(255,255,255,0.9) inset, 0px 2px 2px rgba(0,0,0,0.1);
}

#accordion-content label:hover{
	background: #fff;
}
#accordion-content input:checked + label,
#accordion-content input:checked + label:hover{
	background: #c6e1ec;
	color: #3d7489;
	text-shadow: 0px 1px 1px rgba(255,255,255, 0.6);
	box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3), 0px 2px 2px rgba(0,0,0,0.1);
}
#accordion-content label:hover:after,
#accordion-content input:checked + label:hover:after{
	content: '';
	position: absolute;
	width: 24px;
	height: 24px;
	right: 13px;
	top: 7px;
	background: transparent url(../images/arrow_down.png) no-repeat center center;	
}
#accordion-content input:checked + label:hover:after{
	background-image: url(../images/arrow_up.png);
}
#accordion-content input{
	display: none;
}
#accordion-content section{
	background: rgba(255, 255, 255, 0.5);
	margin-top: -1px;
	overflow: hidden;
	height: 0px;
	position: relative;
	z-index: 10;
	-webkit-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
	-moz-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
	-o-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
	-ms-transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
	transition: height 0.3s ease-in-out, box-shadow 0.6s linear;
}

#accordion-content section p{
	font-style: italic;
	color: #777;
	line-height: 23px;
	font-size: 14px;
	padding: 20px;
	text-shadow: 1px 1px 1px rgba(255,255,255,0.8);
}

#accordion-content section ul {
	padding: 15px 20px;
}

#accordion-content section ul li {
	list-style: none;
	font-size: 14px;
	margin-bottom: 10px;
	background: url(../images/recent_li_bg.gif) no-repeat left center;
	padding-left: 15px;
}

#accordion-content section ul li a {
	color: #ac0202;
}

#accordion-content section ul li a:hover {
	color: #888;
}

#accordion-content input:checked ~ section{
	-webkit-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-moz-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-o-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-ms-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3);
}

#accordion-content input:checked ~ section.tab{
	height: 140px;
}

Mình giải thích những đoạn quan trọng trong đoạn CSS trên.

 
input:checked + label

Dấu ” + ” trong CSS có nghĩa là chọn thẻ con đầu tiên ngay sau thẻ mẹ.

 
input:checked ~ section

Dấu ” ~ ” trong CSS có nghĩa là chọn tất cả thẻ con ngay sau thẻ mẹ.

Các bạn lưu ý là thẻ input trong HTML của mình chỉ làm nhiệm vụ là check select tab thôi nhé, nên mình đã display: none;

#accordion-content input:checked + label,
#accordion-content input:checked + label:hover{
	background: #c6e1ec;
	color: #3d7489;
	text-shadow: 0px 1px 1px rgba(255,255,255, 0.6);
	box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3), 0px 2px 2px rgba(0,0,0,0.1);
}

Khi thẻ input được chọn và người dùng di chuột qua thẻ label thì mình sẽ sét background cho thẻ label như trên.

#accordion-content label:hover:after,
#accordion-content input:checked + label:hover:after{
	content: '';
	position: absolute;
	width: 24px;
	height: 24px;
	right: 13px;
	top: 7px;
	background: transparent url(../images/arrow_down.png) no-repeat center center;	
}
#accordion-content input:checked + label:hover:after{
	background-image: url(../images/arrow_up.png);
}
 
#accordion-content input:checked + label:hover:after{
	background-image: url(../images/arrow_up.png);
}

Thuộc tính after trong CSS có nghĩa là thêm nội dung phía sau thành phần, khi người dùng di chuột qua mình sẽ thêm cái dấu mũi tên vào ngay góc tay phải, lưu ý là bạn phải sét position: relative cho thẻ label rồi bạn mới sử dụng absolute được nhé.

#accordion-content input:checked ~ section{
	-webkit-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-moz-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-o-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	-ms-transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	transition: height 0.5s ease-in-out, box-shadow 0.1s linear;
	box-shadow: 0px 0px 0px 1px rgba(155,155,155,0.3);
}

#accordion-content input:checked ~ section.tab{
	height: 140px;
}

Khi input được chọn thì mình sẽ show nội dung của nó nằm trong thẻ section ra trong khoảng thời gian là 0.5s, bắt buộc bạn phải sét height cho nó thì khi tab được chọn thì nó mới bắt đầu lấy height của tab đó và show ra.