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 ido infoi) tak, że jest widoczny w poprzednim elementem (jednego z classz 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, #infoiaby pojawił się w pierwszym elemencie, który nazwiemy .navi. W szczególności chcemy #infoiznaleźć 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 positionwartości są relative, absolute, sticky, i fixed. Ustawiając element na positionjedną 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: 100pxaby ustawić element w odległości 100 pikseli od góry strony. I odwrotnie, jeśli ustawimy, bottom: 100pxelement zostanie umieszczony 100 pikseli od dołu strony.
Tutaj gubi się wielu początkujących CSS -position: absolutema punkt odniesienia. W powyższym przykładzie ramką odniesienia jestbodyelement. position: absoluteotop: 100pxoznacza, że element jest umieszczony 100 pikseli z górybodyelementu.
Ramkę odniesienia lub kontekst pozycji można zmienić, ustawiając positionelement 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: absolutei 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-indexlub 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ć, toppojawia 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 #infoielementu, aby pojawił się w .navielemencie. W tym celu zawiniemy elementy .navii #infoiw 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 ..wrapperposition: relative
.wrapper {
position: relative;
}
Dzięki temu nowemu kontekstowi pozycji możemy pozycjonować #infoiwewnątrz .wrapper. Po pierwsze, daje , co pozwala nam na pozycji absolutnie .#infoiposition: absolute#infoi.wrapper
Następnie dodaj top: 0i, right: 0aby ustawić #infoielement w prawym górnym rogu. Pamiętaj, ponieważ ponieważ #infoielement używa .wrapperjako kontekstu pozycji, znajdzie się w prawym górnym rogu .wrapperelementu.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Ponieważ .wrapperjest to tylko pojemnik na .navi, pozycjonowanie #infoiw prawym górnym rogu .wrapperdaje efekt pozycjonowania w prawym górnym rogu .navi.
I mamy to, #infoiteraz 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 .navielementu z #infoielementem po prawej stronie. Użyłem pełnych gridwł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: absolutena #infoielemencie użyjemy position: relative. To pozwala nam zmienić położenie #infoielementu z jego domyślnej pozycji poniżej .navielementu. Za pomocą position: relativemożemy użyć topwartości ujemnej, aby przesunąć ją w górę z jej domyślnej pozycji, a leftwartoś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: visiblezamiast niego.