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 id
di infoi
), quindi appare all'interno dell'elemento precedente (quello con un class
di 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 #infoi
modo che appaia all'interno del primo elemento, che chiameremo .navi
. In particolare, vogliamo #infoi
essere 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 position
valori sono relative
, absolute
, sticky
, e fixed
. Impostando un elemento position
su 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: 100px
per posizionare l'elemento a 100 pixel dalla parte superiore della pagina. Al contrario, se impostiamo bottom: 100px
l'elemento verrebbe posizionato a 100 pixel dalla parte inferiore della pagina.
Ecco dove molti nuovi arrivati CSS si perdono :position: absolute
ha un quadro di riferimento. Nell'esempio sopra, il frame di riferimento è l'body
elemento. position: absolute
contop: 100px
significa che l'elemento è posizionato a 100 pixel dalla parte superiorebody
dell'elemento.
Il frame di riferimento della posizione o il contesto della posizione può essere modificato impostando l' position
elemento 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: absolute
e 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-index
o 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 top
viene 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' #infoi
elemento in modo che appaia all'interno .navi
dell'elemento. Per fare ciò, avvolgiamo gli elementi .navi
e #infoi
in 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 .wrapper
a position: relative
.
.wrapper {
position: relative;
}
Con questo nuovo contesto di posizione, possiamo posizionarci #infoi
all'interno .wrapper
. Innanzitutto, dai #infoi
a position: absolute
, permettendoci di posizionarci #infoi
assolutamente .wrapper
.
Quindi aggiungere top: 0
e right: 0
per posizionare l' #infoi
elemento nell'angolo in alto a destra. Ricorda, poiché l' #infoi
elemento sta usando .wrapper
come contesto di posizione, sarà in alto a destra .wrapper
dell'elemento.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Poiché .wrapper
è semplicemente un contenitore per .navi
, il posizionamento #infoi
nell'angolo in alto a destra di .wrapper
dà l'effetto di essere posizionato nell'angolo in alto a destra di .navi
.
E lì ce l'abbiamo, #infoi
ora 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' .navi
elemento con l' #infoi
elemento all'estrema destra. Ho usato le grid
proprietà 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: absolute
sul #infoi
elemento, useremo position: relative
. Questo ci consente di riposizionare l' #infoi
elemento dalla sua posizione predefinita sotto l' .navi
elemento. Con position: relative
possiamo usare un top
valore negativo per spostarlo verso l'alto dalla sua posizione predefinita, e un left
valore 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: visible
invece.