Przyjęte rozwiązanie działa świetnie, ale IMO nie wyjaśnia, dlaczego działa. Poniższy przykład jest sprowadzony do podstaw i oddziela ważny CSS od nieistotnego CSS w stylu. Jako bonus zamieściłem również szczegółowe wyjaśnienie, jak działa pozycjonowanie CSS.
TLDR; jeśli chcesz tylko kod, przewiń w dół do wyniku .
Problem
Istnieją dwa oddzielne elementy, rodzeństwem, a celem jest, aby umieścić drugi element (o id
o infoi
) tak, że jest widoczny w poprzednim elementem (jednego z class
z navi
). Struktury HTML nie można zmienić.
Proponowane rozwiązanie
Aby osiągnąć pożądany rezultat, będziemy przesuwać lub ustawiać drugi element, który nazwiemy, #infoi
aby pojawił się w pierwszym elemencie, który nazwiemy .navi
. W szczególności chcemy #infoi
znaleźć się w prawym górnym rogu .navi
.
Wymagana wiedza na temat pozycji CSS
CSS ma kilka właściwości dla elementów pozycjonujących. Domyślnie wszystkie elementy są position: static
. Oznacza to, że element zostanie umieszczony zgodnie ze swoją kolejnością w strukturze HTML, z kilkoma wyjątkami.
Pozostałe position
wartości są relative
, absolute
, sticky
, i fixed
. Ustawiając element na position
jedną z tych innych wartości, można teraz zastosować kombinację następujących czterech właściwości do pozycjonowania elementu:
Innymi słowy, ustawiając position: absolute
, możemy dodać, top: 100px
aby ustawić element w odległości 100 pikseli od góry strony. I odwrotnie, jeśli ustawimy, bottom: 100px
element zostanie umieszczony 100 pikseli od dołu strony.
Tutaj gubi się wielu początkujących CSS -position: absolute
ma punkt odniesienia. W powyższym przykładzie ramką odniesienia jestbody
element. position: absolute
otop: 100px
oznacza, że element jest umieszczony 100 pikseli z górybody
elementu.
Ramkę odniesienia lub kontekst pozycji można zmienić, ustawiając position
element nadrzędny na dowolną wartość inną niżposition: static
. Oznacza to, że możemy utworzyć nowy kontekst pozycji, podając element nadrzędny:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Na przykład, jeśli <div class="parent">
podano element position: relative
, wszystkie elementy potomne używają <div class="parent">
jako kontekstu pozycji. Gdyby podano element potomny position: absolute
i top: 100px
, element zostałby umieszczony 100 pikseli od góry <div class="parent">
elementu, ponieważ <div class="parent">
jest to teraz kontekst pozycji.
Innym czynnikiem, o którym należy pamiętać, jest kolejność stosów - lub sposób układania elementów w kierunku Z. Trzeba tutaj wiedzieć, że kolejność elementów jest domyślnie definiowana przez odwrotność ich kolejności w strukturze HTML. Rozważ następujący przykład:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
W tym przykładzie, jeśli dwa <div>
elementy zostałyby umieszczone w tym samym miejscu na stronie, <div>Top</div>
element obejmowałby ten <div>Bottom</div>
element. Ponieważ <div>Top</div>
pojawia się <div>Bottom</div>
w strukturze HTML, ma wyższą kolejność układania.
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>
Kolejność układania można zmienić za pomocą CSS przy użyciu właściwości z-index
lub order
.
W tym wydaniu możemy zignorować kolejność układania, ponieważ naturalna struktura HTML elementów oznacza, że element, na którym chcemy się pojawić, top
pojawia się po drugim elemencie.
Wróćmy więc do problemu - użyjemy kontekstu pozycji, aby rozwiązać ten problem.
Rozwiązanie
Jak wspomniano powyżej, naszym celem jest takie umieszczenie #infoi
elementu, aby pojawił się w .navi
elemencie. W tym celu zawiniemy elementy .navi
i #infoi
w nowy element <div class="wrapper">
, abyśmy mogli utworzyć nowy kontekst pozycji.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Następnie należy utworzyć nowy kontekst pozycji dając ..wrapper
position: relative
.wrapper {
position: relative;
}
Dzięki temu nowemu kontekstowi pozycji możemy pozycjonować #infoi
wewnątrz .wrapper
. Po pierwsze, daje , co pozwala nam na pozycji absolutnie .#infoi
position: absolute
#infoi
.wrapper
Następnie dodaj top: 0
i, right: 0
aby ustawić #infoi
element w prawym górnym rogu. Pamiętaj, ponieważ ponieważ #infoi
element używa .wrapper
jako kontekstu pozycji, znajdzie się w prawym górnym rogu .wrapper
elementu.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Ponieważ .wrapper
jest to tylko pojemnik na .navi
, pozycjonowanie #infoi
w prawym górnym rogu .wrapper
daje efekt pozycjonowania w prawym górnym rogu .navi
.
I mamy to, #infoi
teraz wydaje się być w prawym górnym rogu .navi
.
Wynik
Poniższy przykład sprowadza się do podstaw i zawiera minimalną stylizację.
/*
* 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>
Alternatywne rozwiązanie (siatka)
Oto alternatywne rozwiązanie z wykorzystaniem CSS Grid do pozycjonowania .navi
elementu z #infoi
elementem po prawej stronie. Użyłem pełnych grid
właściwości, aby było to jak najbardziej jasne.
: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>
Alternatywne rozwiązanie (bez opakowania)
W przypadku, gdy nie możemy edytować żadnego HTML, co oznacza, że nie możemy dodać elementu opakowania, nadal możemy osiągnąć pożądany efekt.
Zamiast używać position: absolute
na #infoi
elemencie użyjemy position: relative
. To pozwala nam zmienić położenie #infoi
elementu z jego domyślnej pozycji poniżej .navi
elementu. Za pomocą position: relative
możemy użyć top
wartości ujemnej, aby przesunąć ją w górę z jej domyślnej pozycji, a left
wartości 100%
minus kilka pikseli, używając left: calc(100% - 52px)
, aby ustawić ją w pobliżu prawej strony.
/*
* 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
, użyjoverflow: visible
zamiast niego.