Giải pháp được chấp nhận hoạt động rất tốt, nhưng IMO thiếu một lời giải thích về lý do tại sao nó hoạt động. Ví dụ dưới đây được đưa vào các khái niệm cơ bản và tách CSS quan trọng khỏi CSS kiểu dáng không liên quan. Như một phần thưởng, tôi cũng đã bao gồm một lời giải thích chi tiết về cách hoạt động của định vị CSS.
TLDR; nếu bạn chỉ muốn mã, cuộn xuống Kết quả .
Vấn đề
Có hai riêng biệt, anh chị em, các yếu tố và mục tiêu là để xác định vị trí phần tử thứ hai (với một idsố infoi), vì vậy nó xuất hiện trong các yếu tố trước đó (một với một classsố navi). Cấu trúc HTML không thể thay đổi.
Giải pháp đề xuất
Để đạt được kết quả mong muốn, chúng tôi sẽ di chuyển, hoặc vị trí, phần tử thứ hai, mà chúng tôi sẽ gọi #infoiđể nó xuất hiện trong phần tử đầu tiên, chúng tôi sẽ gọi .navi. Cụ thể, chúng tôi muốn #infoiđược định vị ở góc trên bên phải .navi.
Kiến thức CSS cần thiết
CSS có một số thuộc tính cho các yếu tố định vị. Theo mặc định, tất cả các yếu tố là position: static. Điều này có nghĩa là phần tử sẽ được định vị theo thứ tự của nó trong cấu trúc HTML, với một vài ngoại lệ.
Khác positiongiá trị relative, absolute, sticky, và fixed. Bằng cách đặt một phần tử positionthành một trong những giá trị khác, giờ đây có thể sử dụng kết hợp bốn thuộc tính sau để định vị phần tử:
Nói cách khác, bằng cách cài đặt position: absolute, chúng ta có thể thêm top: 100pxvào vị trí phần tử 100 pixel từ đầu trang. Ngược lại, nếu chúng ta đặt bottom: 100pxthành phần sẽ được định vị 100 pixel từ cuối trang.
Đây là nơi nhiều người mới CSS bị lạc -position: absolutecó một khung tham chiếu. Trong ví dụ trên, khung tham chiếu làbodyphần tử. position: absolutevớitop: 100pxnghĩa là phần tử được định vị 100 pixel từ đỉnh củabodyphần tử.
Khung vị trí của tham chiếu hoặc bối cảnh vị trí, có thể được thay đổi bằng cách đặt positionphần tử cha thành bất kỳ giá trị nào khácposition: static . Đó là, chúng ta có thể tạo bối cảnh vị trí mới bằng cách đưa ra một phần tử cha:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Ví dụ: nếu một <div class="parent">phần tử được đưa ra position: relative, bất kỳ phần tử con nào cũng sử dụng <div class="parent">làm bối cảnh vị trí của chúng. Nếu một phần tử con được đưa ra position: absolutevà top: 100px, phần tử đó sẽ được định vị 100 pixel từ đỉnh của <div class="parent">phần tử, vì <div class="parent">bây giờ là bối cảnh vị trí.
Yếu tố khác cần lưu ý là thứ tự ngăn xếp - hoặc cách các yếu tố được xếp chồng theo hướng z. Điều cần biết ở đây là thứ tự ngăn xếp của các phần tử, theo mặc định, được xác định bởi sự đảo ngược thứ tự của chúng trong cấu trúc HTML. Hãy xem xét ví dụ sau:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
Trong ví dụ này, nếu hai <div>phần tử được định vị ở cùng một vị trí trên trang, <div>Top</div>phần tử sẽ bao phủ <div>Bottom</div>phần tử. Vì <div>Top</div>xuất hiện sau <div>Bottom</div>trong cấu trúc HTML, nó có thứ tự xếp chồng cao hơn.
div {
position: absolute;
width: 50%;
height: 50%;
}
#bottom {
top: 0;
left: 0;
background-color: blue;
}
#top {
top: 25%;
left: 25%;
background-color: red;
}
<div id="bottom">Bottom</div>
<div id="top">Top</div>
Thứ tự sắp xếp có thể được thay đổi bằng CSS bằng cách sử dụng z-indexhoặc ordercác thuộc tính.
Chúng ta có thể bỏ qua thứ tự sắp xếp trong vấn đề này vì cấu trúc HTML tự nhiên của các phần tử có nghĩa là phần tử mà chúng ta muốn xuất hiện xuất hiện topsau phần tử khác.
Vì vậy, quay trở lại vấn đề trong tay - chúng tôi sẽ sử dụng bối cảnh vị trí để giải quyết vấn đề này.
Giải pháp
Như đã nêu ở trên, mục tiêu của chúng tôi là định vị #infoiphần tử để nó xuất hiện trong .naviphần tử. Để làm điều này, chúng tôi sẽ bọc .navivà #infoicác yếu tố trong một yếu tố mới <div class="wrapper">để chúng tôi có thể tạo bối cảnh vị trí mới.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Sau đó tạo bối cảnh vị trí mới bằng cách đưa ra .wrappera position: relative.
.wrapper {
position: relative;
}
Với bối cảnh vị trí mới này, chúng ta có thể định vị #infoitrong .wrapper. Đầu tiên, đưa ra #infoimột position: absolute, cho phép chúng tôi vị trí #infoihoàn toàn trong .wrapper.
Sau đó thêm top: 0và right: 0định vị #infoiphần tử ở góc trên bên phải. Hãy nhớ rằng, vì #infoiphần tử đang sử dụng .wrapperlàm bối cảnh vị trí của nó, nên nó sẽ nằm ở phía trên bên phải của .wrapperphần tử.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Bởi vì .wrapperchỉ đơn thuần là một thùng chứa .navi, định vị #infoiở góc trên bên phải .wrappermang lại hiệu quả của việc được định vị ở góc trên bên phải .navi.
Và ở đó chúng tôi có nó, #infoibây giờ dường như ở góc trên bên phải của .navi.
Kết quả
Ví dụ dưới đây được đưa vào những điều cơ bản và chứa một số kiểu dáng tối thiểu.
/*
* position: relative gives a new position context
*/
.wrapper {
position: relative;
}
/*
* The .navi properties are for styling only
* These properties can be changed or removed
*/
.navi {
background-color: #eaeaea;
height: 40px;
}
/*
* Position the #infoi element in the top-right
* of the .wrapper element
*/
#infoi {
position: absolute;
top: 0;
right: 0;
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
height: 20px;
padding: 10px 10px;
}
<div class="wrapper">
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>
</div>
Một giải pháp thay thế (lưới)
Đây là một giải pháp thay thế sử dụng CSS Grid để định vị .naviphần tử với #infoiphần tử ở phía bên phải. Tôi đã sử dụng các gridthuộc tính dài dòng để làm cho nó rõ ràng nhất có thể.
:root {
--columns: 12;
}
/*
* Setup the wrapper as a Grid element, with 12 columns, 1 row
*/
.wrapper {
display: grid;
grid-template-columns: repeat(var(--columns), 1fr);
grid-template-rows: 40px;
}
/*
* Position the .navi element to span all columns
*/
.navi {
grid-column-start: 1;
grid-column-end: span var(--columns);
grid-row-start: 1;
grid-row-end: 2;
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
background-color: #eaeaea;
}
/*
* Position the #infoi element in the last column, and center it
*/
#infoi {
grid-column-start: var(--columns);
grid-column-end: span 1;
grid-row-start: 1;
place-self: center;
}
<div class="wrapper">
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>
</div>
Một giải pháp thay thế (Không có Wrapper)
Trong trường hợp chúng tôi không thể chỉnh sửa bất kỳ HTML nào, có nghĩa là chúng tôi không thể thêm phần tử trình bao bọc, chúng tôi vẫn có thể đạt được hiệu quả mong muốn.
Thay vì sử dụng position: absolutetrên #infoiphần tử, chúng tôi sẽ sử dụng position: relative. Điều này cho phép chúng ta định vị lại #infoiphần tử từ vị trí mặc định bên dưới .naviphần tử. Với position: relativechúng ta có thể sử dụng một topgiá trị âm để di chuyển nó lên từ vị trí mặc định của nó và leftgiá trị 100%trừ đi một vài pixel, bằng cách sử dụng left: calc(100% - 52px), để đặt nó ở gần bên phải.
/*
* The .navi properties are for styling only
* These properties can be changed or removed
*/
.navi {
background-color: #eaeaea;
height: 40px;
width: 100%;
}
/*
* Position the #infoi element in the top-right
* of the .wrapper element
*/
#infoi {
position: relative;
display: inline-block;
top: -40px;
left: calc(100% - 52px);
/*
* Styling only, the below can be changed or removed
* depending on your use case
*/
height: 20px;
padding: 10px 10px;
}
<div class="navi"></div>
<div id="infoi">
<img src="http://via.placeholder.com/32x20/000000/ffffff?text=?" height="20" width="32"/>
</div>
overflow: hidden,overflow: visiblethay vào đó hãy sử dụng .