Solusi yang diterima bekerja dengan baik, tetapi IMO tidak memiliki penjelasan mengapa itu bekerja. Contoh di bawah ini diringkas menjadi dasar-dasar dan memisahkan CSS penting dari CSS styling yang tidak relevan. Sebagai bonus, saya juga menyertakan penjelasan terperinci tentang cara kerja pemosisian CSS.
TLDR; jika Anda hanya menginginkan kode, gulir ke bawah ke Hasil .
Masalah
Ada dua terpisah, saudara, unsur-unsur dan tujuannya adalah untuk posisi elemen kedua (dengan id
dari infoi
), agar muncul dalam elemen sebelumnya (yang dengan class
darinavi
). Struktur HTML tidak dapat diubah.
Solusi yang Diusulkan
Untuk mencapai hasil yang diinginkan, kita akan memindahkan, atau memposisikan, elemen kedua, yang akan kita panggil #infoi
sehingga muncul di dalam elemen pertama, yang akan kita panggil .navi
. Secara khusus, kami ingin #infoi
diposisikan di sudut kanan atas.navi
.
Pengetahuan yang Diperlukan Posisi CSS
CSS memiliki beberapa properti untuk elemen penentuan posisi. Secara default, semua elemen adalah position: static
. Ini berarti elemen akan diposisikan sesuai dengan urutannya dalam struktur HTML, dengan beberapa pengecualian.
Yang lain position
nilai-nilai relative
, absolute
, sticky
, dan fixed
. Dengan menyetel elemen position
ke salah satu dari nilai-nilai lain ini sekarang mungkin untuk menggunakan kombinasi dari empat properti berikut untuk memposisikan elemen:
Dengan kata lain, dengan mengatur position: absolute
, kita dapat menambahkan top: 100px
ke posisi elemen 100 piksel dari bagian atas halaman. Sebaliknya, jika kita mengatur bottom: 100px
elemen akan diposisikan 100 piksel dari bagian bawah halaman.
Di sinilah banyak pendatang CSS tersesat -position: absolute
memiliki kerangka referensi. Dalam contoh di atas, kerangka acuan adalahbody
elemen. position: absolute
dengantop: 100px
cara elemen diposisikan 100 piksel dari bagian atasbody
elemen.
Kerangka posisi referensi, atau konteks posisi, dapat diubah dengan mengatur position
elemen induk ke nilai apa pun selainposition: static
. Artinya, kita dapat membuat konteks posisi baru dengan memberikan elemen induk:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Misalnya, jika <div class="parent">
elemen diberikan position: relative
, elemen anak mana pun menggunakan <div class="parent">
konteks posisi mereka. Jika elemen anak diberikan position: absolute
dan top: 100px
, elemen akan diposisikan 100 piksel dari bagian atas <div class="parent">
elemen, karena<div class="parent">
sekarang adalah konteks posisi.
Faktor lain yang harus diperhatikan adalah susunan tumpukan - atau bagaimana elemen ditumpuk dalam arah-z. Yang harus diketahui di sini adalah susunan elemen, secara default, ditentukan oleh kebalikan dari urutannya dalam struktur HTML. Perhatikan contoh berikut:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
Dalam contoh ini, jika dua <div>
elemen diposisikan di tempat yang sama pada halaman, <div>Top</div>
elemen tersebut akan menutupi <div>Bottom</div>
elemen tersebut. Sejak <div>Top</div>
muncul setelah <div>Bottom</div>
dalam struktur HTML memiliki urutan susun yang lebih tinggi.
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>
Urutan susun dapat diubah dengan CSS menggunakan properti z-index
atau order
.
Kita dapat mengabaikan urutan penumpukan dalam masalah ini karena struktur HTML alami dari elemen berarti elemen yang ingin kita tampilkan top
muncul setelah elemen lainnya.
Jadi, kembali ke masalah yang ada - kita akan menggunakan konteks posisi untuk menyelesaikan masalah ini.
Solusinya
Seperti yang dinyatakan di atas, tujuan kami adalah memposisikan #infoi
elemen sehingga muncul di dalam .navi
elemen. Untuk melakukan ini, kami akan membungkus .navi
dan #infoi
elemen dalam elemen baru <div class="wrapper">
sehingga kami dapat membuat konteks posisi baru.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Kemudian buat konteks posisi baru dengan memberikan .wrapper
a position: relative
.
.wrapper {
position: relative;
}
Dengan konteks posisi baru ini, kita dapat memposisikan #infoi
dalam .wrapper
. Pertama, beri #infoi
a position: absolute
, yang memungkinkan kita untuk memposisikan secara #infoi
mutlak .wrapper
.
Kemudian tambahkan top: 0
dan right: 0
posisikan #infoi
elemen di sudut kanan atas. Ingat, karena #infoi
elemen menggunakan .wrapper
konteks posisinya, elemen akan berada di kanan atas .wrapper
elemen.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Karena .wrapper
hanyalah wadah untuk .navi
, memposisikan #infoi
di sudut kanan atas .wrapper
memberikan efek diposisikan di sudut kanan atas.navi
.
Dan begitulah, #infoi
sekarang tampaknya berada di sudut kanan atas .navi
.
Hasil
Contoh di bawah ini diringkas ke dasar-dasarnya, dan berisi beberapa gaya minimal.
/*
* 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>
Solusi Alternatif (Kotak)
Inilah solusi alternatif menggunakan CSS Grid untuk memposisikan .navi
elemen dengan #infoi
elemen di paling kanan. Saya telah menggunakan grid
properti verbose untuk membuatnya sejelas mungkin.
: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>
Solusi Alternatif (Tanpa Pembungkus)
Jika kami tidak dapat mengedit HTML apa pun, artinya kami tidak dapat menambahkan elemen pembungkus, kami masih dapat mencapai efek yang diinginkan.
Alih-alih menggunakan position: absolute
pada #infoi
elemen, kita akan menggunakan position: relative
. Ini memungkinkan kami untuk memposisikan ulang #infoi
elemen dari posisi default di bawah .navi
elemen. Dengan position: relative
kita dapat menggunakan top
nilai negatif untuk memindahkannya dari posisi default, dan left
nilai 100%
minus beberapa piksel, menggunakan left: calc(100% - 52px)
, untuk memposisikannya di dekat sisi kanan.
/*
* 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
, gunakanoverflow: visible
sebagai gantinya.