Hướng dẫn css timeline vertical
Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article) Show Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách xây dựng một timeline đứng từ đầu cho đến cuối. Trước tiên, chúng ta sẽ tạo cấu trúc cơ bản với mã ít mã html nhất và tận dụng sức mạnh của phần tử giả CSS. Sau đó, chúng ta sẽ sử dụng một số JavaScript để thêm một số hiệu ứng chuyển tiếp như khi chúng ta cuộn trang xuống. Hãy xem trước những gì chúng ta sẽ xây dựng (kiểm tra phiên bản lớn hơn trên CodePen). 1. Mã đánh dấu HTMLMã đánh dấu mà chúng ta sẽ sử dụng
là khá đơn giản; một danh sách không thứ tự đơn giản với một phần tử Ngoài ra, chúng ta sẽ bao quanh toàn bộ mọi thứ bên trong một phần tử
Điều này cho chúng ta kết quả chưa định hình phong cách như dưới đây: 2. Thêm các phong cách CSS ban đầuSau một số màu cơ bản, vân vân (xem phần trên của CSS pen dưới đây), chúng ta sẽ xác định một số thuộc tính cấu trúc CSS cho các phần tử danh sách. Chúng ta cũng sẽ định phong cách cho phần tử giả .timeline ul li { list-style-type: none; position: relative; width: 6px; margin: 0 auto; padding-top: 50px; background: #fff; } .timeline ul li::after { content: ''; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%); width: 30px; height: 30px; border-radius: 50%; background: inherit; } Tôi đã xoá nội dung trong các phần tử của danh sách để đảm bảo bước này rõ ràng hơn, mang lại cho chúng ta những điều sau đây: 3. Các phong cách cho phần tử TimelineBây giờ chúng ta hãy định phong cách
phần tử Ngoài ra, như chúng ta sẽ thấy trong một lúc nữa, không phải tất cả phần tử div đều chia sẻ chung một phong cách. Cảm ơn các phần tử giả CSS Hãy xem các thuộc tính CSS tương ứng dưới đây: .timeline ul li div { position: relative; bottom: 0; width: 400px; padding: 15px; background: #F45B69; } .timeline ul li div::before { content: ''; position: absolute; bottom: 7px; width: 0; height: 0; border-style: solid; } Sau đó một số phong cách cho các phần tử lẻ của chúng ta: .timeline ul li:nth-child(odd) div { left: 45px; } .timeline ul li:nth-child(odd) div::before { left: -15px; border-width: 8px 16px 8px 0; border-color: transparent #F45B69 transparent transparent; } Sau cùng, là các phong cách cho các phần tử chẵn: .timeline ul li:nth-child(even) div { left: -439px; } .timeline ul li:nth-child(even) div::before { right: -15px; border-width: 8px 0 8px 16px; border-color: transparent transparent transparent #F45B69; } Với những thuộc tính này đã sẵn sàng (và HTML của chúng ta một lần nữa đã có nội dung) timeline của chúng ta trông như sau: Sự khác nhau chính giữa các thẻ div "lẻ" và "chẵn" là vị trí của chúng. Những cái đầu tiên có Chiều rộng của mỗi div + khoảng cách mong muốn - Chiều rộng của mỗi phần tử của danh sách = 400px + 45px -6px = 439px Sự khác biệt thứ hai, ít quan trọng hơn là tạo mũi tên bằng phần tử giả của chúng. Điều đó có nghĩa là, các phần tử giả của mỗi div "lẻ" có một mũi tên hướng về bên trái, trong khi các phần tử giả của các div "chẵn" sẽ hiển thị như một mũi tên hướng về bên phải. 4. Thêm tương tácBây giờ thì cấu trúc cơ bản của timeline đã sẵn sàng, hãy xem xét những yêu cầu mới:
Nhiệm vụ đầu tiên là tương đối đơn giản. Dù vậy, cái thứ hai, phức tạp hơn một chút. Chúng ta cần phải xác định nếu các phần tử mục tiêu (các phần tử của danh mục) là hoàn toàn hiển thị trong viewport hiện tại, sau đó nếu điều đó xảy ra chúng ta hiển thị phần tử con của chúng. Để cài đặt tính năng này, chúng ta sẽ không sử dụng bất kỳ thư viện JavaScript bên ngoài nào (ví dụ như WOW.js hoặc ScrollReveal.js) hoặc viết mã riêng của chúng ta, khá phức tạp. Rất may là có một chủ đề rất phổ biến trên StackOverlow về vấn đề này. Vì vậy, trước tiên chúng ta hãy tận dụng lợi thế của câu trả lời được đề xuất để kiểm tra xem một phần tử được nhìn thấy trong viewport hiện tại hay không. Dưới đây là hàm được đơn giản hoá mà chúng ta sẽ sử dụng: function isElementInViewport(el) { var rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); } Thêm lớpTiếp theo chúng ta thêm lớp Lưu ý: điều quan trọng là chúng ta kiểm tra nếu chúng có thể hiển thị trong các trường hợp sau đây:
Nếu cần thiết, chúng ta có thể làm một số bài test bổ sung (chẳng hạn như khi thay đổi kích cỡ của cửa sổ trình duyệt). Trong ví dụ của chúng ta, đây là mã mà chúng ta sử dụng: var items = document.querySelectorAll(".timeline li"); // code for the isElementInViewport function function callbackFunc() { for (var i = 0; i < items.length; i++) { if (isElementInViewport(items[i])) { items[i].classList.add("in-view"); } } } window.addEventListener("load", callbackFunc); window.addEventListener("scroll", callbackFunc); Bây giờ thì chúng ta đã thêm JavaScript của chúng ta, nếu chúng ta tải lại trang web, chúng ta sẽ thấy một kết quả tương tự như thế này: Ẩn đi và hiển thị trở lạiBây giờ hãy xem xét lại yêu
cầu đầu tiên của chúng ta. Hãy nhớ rằng, mặc định, tất cả div sẽ được ẩn. Để đạt được điều này, chúng ta sử dụng các thuộc tính Cuối
cùng, một vấn đề nhỏ khác, những gì chúng ta sẽ làm khi một phần tử Các phong cách sau giải quyết tất cả điều đó: .timeline ul li::after { background: #fff; transition: background .5s ease-in-out; } .timeline ul li.in-view::after { background: #F45B69; } .timeline ul li div { visibility: hidden; opacity: 0; transition: all .5s ease-in-out; } .timeline ul li:nth-child(odd) div { transform: translate3d(200px,0,0); } .timeline ul li:nth-child(even) div { transform: translate3d(-200px,0,0); } .timeline ul li.in-view div { transform: none; visibility: visible; opacity: 1; } Hình minh hoạt dưới đây thể hiện trạng thái ban đầu của timeline. Ở đây bạn sẽ nhìn thấy các phần tử của timeline bởi vì tôi đã cho chúng một ít opacity để minh họa vị trí ban đầu của chúng: Và đây là trạng thái sau cùng của timeline: 5. Tạo khả năng đáp ứng (Responsive)Chúng ta đã gần xong! Điều cuối cùng mà chúng ta phải làm là làm cho timeline của chúng ta có khả năng đáp ứng. Đầu tiên, trên các màn hình mà chúng ta cho là "các màn hình trung bình" (>600px và ≤900px), chúng ta chỉ tạo một thay đổi nhỏ. Cụ thể, chúng ta giảm chiều rộng của các phần tử div. Dưới đây là các thuộc tính mà chúng ta phải thay đổi: @media screen and (max-width: 900px) { .timeline ul li div { width: 250px; } .timeline ul li:nth-child(even) div { left: -289px; /*250+45-6*/ } } Trong trường hợp này, timeline sẽ như trông như sau: Tuy nhiên trên các màn hình nhỏ (≤600px), tất cả các phần tử của timeline đều giống nhau; không có sự khác biệt giữa các thẻ div "lẻ" và "chẵn". Một lần nữa, chúng ta phải thay thế một số thuộc tính CSS: @media screen and (max-width: 600px) { .timeline ul li { margin-left: 20px; } .timeline ul li div { width: calc(100vw - 91px); } .timeline ul li:nth-child(even) div { left: 45px; } .timeline ul li:nth-child(even) div::before { left: -15px; border-width: 8px 16px 8px 0; border-color: transparent #F45B69 transparent transparent; } } Trên các màn hình nhỏ thì timeline sẽ trông giống như sau: Lưu ý: trên các màn hình nhỏ chúng ta sử dụng đơn vị Trình duyệt hỗ trợBản demo làm việc tốt trong hầu hết các trình duyệt và thiết bị hiện đại. Tuy nhiên, trên các thiết bị iOS, các phần tử của timeline luôn luôn hiển thị, thay vì xuất hiện khi phần tử cha của chúng đi vào viewport. Từ thử nghiệm của tôi, tôi đã thấy trên những thiết bị mà thuộc tính Mặc dù nó không phải là một vấn đề lớn (bạn có thể muốn những hiệu ứng động chỉ có ở trên màn hình lớn), nếu bạn biết thêm về vấn đề này hoặc bạn đã nhìn thấy nó trước, đừng quên để lại ý kiến trong phần bình luận. Kết luậnTrong hướng dẫn này, chúng ta đã tạo ra một timeline đứng có tính đáp ứng cao. Chúng ta đã tìm hiểu rất nhiều điều, vì vậy chúng ta hãy tóm tắt lại:
Tôi hy vọng bạn thích hướng dẫn này và bạn sẽ sử dụng timeline này làm cơ sở cho việc xây dựng một cái gì đó thú vị. Nếu bạn có bất kỳ câu hỏi nào, hãy cho tôi biết trong phần bình luận dưới đây! |