La soluzione accettata funziona alla grande, ma all'IMO manca una spiegazione del perché funzioni. L'esempio che segue è ridotto alle basi e separa il CSS importante dal CSS di stile non rilevante. Come bonus, ho anche incluso una spiegazione dettagliata di come funziona il posizionamento CSS.
TLDR; se desideri solo il codice, scorri verso il basso fino a Il risultato .
Il problema
Esistono due elementi separati, fratelli e sorelle, e l'obiettivo è posizionare il secondo elemento (con un iddi infoi), quindi appare all'interno dell'elemento precedente (quello con un classdi navi). La struttura HTML non può essere modificata.
La soluzione proposta
Per ottenere il risultato desiderato, sposteremo o posizioneremo il secondo elemento, che chiameremo in #infoimodo che appaia all'interno del primo elemento, che chiameremo .navi. In particolare, vogliamo #infoiessere posizionati nell'angolo in alto a destra di .navi.
Conoscenza richiesta posizione CSS
CSS ha diverse proprietà per posizionare gli elementi. Per impostazione predefinita, tutti gli elementi sono position: static. Ciò significa che l'elemento verrà posizionato in base al suo ordine nella struttura HTML, con poche eccezioni.
Gli altri positionvalori sono relative, absolute, sticky, e fixed. Impostando un elemento positionsu uno di questi altri valori è ora possibile utilizzare una combinazione delle seguenti quattro proprietà per posizionare l'elemento:
In altre parole, impostando position: absolute, possiamo aggiungere top: 100pxper posizionare l'elemento a 100 pixel dalla parte superiore della pagina. Al contrario, se impostiamo bottom: 100pxl'elemento verrebbe posizionato a 100 pixel dalla parte inferiore della pagina.
Ecco dove molti nuovi arrivati CSS si perdono :position: absoluteha un quadro di riferimento. Nell'esempio sopra, il frame di riferimento è l'bodyelemento. position: absolutecontop: 100pxsignifica che l'elemento è posizionato a 100 pixel dalla parte superiorebodydell'elemento.
Il frame di riferimento della posizione o il contesto della posizione può essere modificato impostando l' positionelemento di un elemento padre su qualsiasi valore diverso daposition: static . Cioè, possiamo creare un nuovo contesto di posizione dando un elemento genitore:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Ad esempio, se <div class="parent">viene fornito un elemento position: relative, tutti gli elementi figlio utilizzano il <div class="parent">loro contesto di posizione. Se fosse dato un elemento figlio position: absolutee top: 100px, l'elemento verrebbe posizionato a 100 pixel dalla parte superiore <div class="parent">dell'elemento, poiché <div class="parent">ora è il contesto della posizione.
L'altro fattore da tenere in considerazione è l' ordine di impilamento o il modo in cui gli elementi vengono impilati nella direzione z. L'obbligo da sapere qui è che l'ordine di stack degli elementi è, per impostazione predefinita, definito dall'inverso del loro ordine nella struttura HTML. Considera il seguente esempio:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
In questo esempio, se i due <div>elementi fossero posizionati nello stesso punto della pagina, l' <div>Top</div>elemento coprirebbe l' <div>Bottom</div>elemento. Poiché <div>Top</div>viene dopo <div>Bottom</div>nella struttura HTML ha un ordine di impilamento più elevato.
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>
L'ordine di sovrapposizione può essere modificato con CSS utilizzando le proprietà z-indexo order.
In questo numero possiamo ignorare l'ordine di sovrapposizione poiché la struttura HTML naturale degli elementi indica che l'elemento su cui vogliamo apparire topviene dopo l'altro elemento.
Quindi, tornando al problema a portata di mano - useremo il contesto di posizione per risolvere questo problema.
La soluzione
Come detto sopra, il nostro obiettivo è posizionare l' #infoielemento in modo che appaia all'interno .navidell'elemento. Per fare ciò, avvolgiamo gli elementi .navie #infoiin un nuovo elemento in <div class="wrapper">modo da poter creare un nuovo contesto di posizione.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Quindi creare un nuovo contesto di posizione dando .wrappera position: relative.
.wrapper {
position: relative;
}
Con questo nuovo contesto di posizione, possiamo posizionarci #infoiall'interno .wrapper. Innanzitutto, dai #infoia position: absolute, permettendoci di posizionarci #infoiassolutamente .wrapper.
Quindi aggiungere top: 0e right: 0per posizionare l' #infoielemento nell'angolo in alto a destra. Ricorda, poiché l' #infoielemento sta usando .wrappercome contesto di posizione, sarà in alto a destra .wrapperdell'elemento.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Poiché .wrapperè semplicemente un contenitore per .navi, il posizionamento #infoinell'angolo in alto a destra di .wrapperdà l'effetto di essere posizionato nell'angolo in alto a destra di .navi.
E lì ce l'abbiamo, #infoiora sembra essere nell'angolo in alto a destra di .navi.
Il risultato
L'esempio che segue è ridotto ai concetti di base e contiene uno stile minimo.
/*
* 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>
Una soluzione alternativa (griglia)
Ecco una soluzione alternativa che utilizza CSS Grid per posizionare l' .navielemento con l' #infoielemento all'estrema destra. Ho usato le gridproprietà verbose per renderlo il più chiaro possibile.
: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>
Una soluzione alternativa (senza involucro)
Nel caso in cui non possiamo modificare alcun HTML, nel senso che non possiamo aggiungere un elemento wrapper, possiamo comunque ottenere l'effetto desiderato.
Invece di utilizzare position: absolutesul #infoielemento, useremo position: relative. Questo ci consente di riposizionare l' #infoielemento dalla sua posizione predefinita sotto l' .navielemento. Con position: relativepossiamo usare un topvalore negativo per spostarlo verso l'alto dalla sua posizione predefinita, e un leftvalore 100%meno un paio di pixel, usando left: calc(100% - 52px), per posizionarlo vicino al lato destro.
/*
* 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, usaoverflow: visibleinvece.