A solução aceita funciona muito bem, mas a IMO não tem uma explicação sobre o motivo. O exemplo abaixo é resumido ao básico e separa o CSS importante do CSS de estilo não relevante. Como bônus, também incluí uma explicação detalhada de como o posicionamento CSS funciona.
TLDR; se você deseja apenas o código, role para baixo até O resultado .
O problema
Existem dois elementos separados, irmãos, e o objetivo é posicionar o segundo elemento (com um id
de infoi
), para que ele apareça no elemento anterior (aquele com um class
de navi
). A estrutura HTML não pode ser alterada.
Solução proposta
Para alcançar o resultado desejado, vamos mover ou posicionar o segundo elemento, que chamaremos #infoi
para que apareça no primeiro elemento, que chamaremos .navi
. Especificamente, queremos #infoi
ser posicionados no canto superior direito de .navi
.
Posição CSS Conhecimento necessário
CSS possui várias propriedades para elementos de posicionamento. Por padrão, todos os elementos são position: static
. Isso significa que o elemento será posicionado de acordo com sua ordem na estrutura HTML, com poucas exceções.
Os outros position
valores são relative
, absolute
, sticky
, e fixed
. Ao definir um elemento position
para um desses outros valores, agora é possível usar uma combinação das quatro propriedades a seguir para posicionar o elemento:
Em outras palavras, ao definir position: absolute
, podemos adicionar top: 100px
para posicionar o elemento 100 pixels da parte superior da página. Por outro lado, se definirmos bottom: 100px
o elemento, ele será posicionado a 100 pixels da parte inferior da página.
Aqui é onde muitos novatos em CSS se perdem -position: absolute
tem um quadro de referência. No exemplo acima, o quadro de referência é obody
elemento position: absolute
comtop: 100px
significa que o elemento está posicionado a 100 pixels da parte superior dobody
elemento.
O quadro de referência da posição, ou o contexto da posição, pode ser alterado definindo o position
elemento pai de qualquer valor diferente deposition: static
. Ou seja, podemos criar um novo contexto de posição fornecendo um elemento pai:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Por exemplo, se um <div class="parent">
elemento é fornecido position: relative
, qualquer elemento filho usa o <div class="parent">
como contexto de posição. Se um elemento filho fosse fornecido position: absolute
e top: 100px
, o elemento seria posicionado a 100 pixels da parte superior do <div class="parent">
elemento, porque <div class="parent">
agora é o contexto da posição.
O outro fator a ser observado é a ordem da pilha - ou como os elementos são empilhados na direção z. O que você deve saber aqui é que a ordem dos elementos da pilha é, por padrão, definida pelo inverso de sua ordem na estrutura HTML. Considere o seguinte exemplo:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
Neste exemplo, se os dois <div>
elementos fossem posicionados no mesmo lugar na página, o <div>Top</div>
elemento cobriria o <div>Bottom</div>
elemento. Como <div>Top</div>
vem depois <div>Bottom</div>
na estrutura HTML, ele tem uma ordem de empilhamento mais alta.
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>
A ordem de empilhamento pode ser alterada com CSS usando as propriedades z-index
ou order
.
Podemos ignorar a ordem de empilhamento nesta edição, pois a estrutura HTML natural dos elementos significa que o elemento em que queremos que apareça top
vem após o outro elemento.
Então, voltando ao problema em questão - usaremos o contexto da posição para resolver esse problema.
A solução
Como mencionado acima, nosso objetivo é posicionar o #infoi
elemento para que ele apareça dentro do .navi
elemento. Para fazer isso, agruparemos os elementos .navi
e #infoi
em um novo elemento <div class="wrapper">
para que possamos criar um novo contexto de posição.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Em seguida, crie um novo contexto de posição dando .wrapper
a position: relative
.
.wrapper {
position: relative;
}
Com este novo contexto de posição, podemos posicionar #infoi
dentro .wrapper
. Primeiro, dê #infoi
a position: absolute
, permitindo-nos posicionar #infoi
absolutamente .wrapper
.
Em seguida, adicione top: 0
e right: 0
para posicionar o #infoi
elemento no canto superior direito. Lembre-se, como o #infoi
elemento está usando .wrapper
como contexto de posição, ele estará no canto superior direito do .wrapper
elemento.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Como .wrapper
é apenas um contêiner para .navi
, o posicionamento #infoi
no canto superior direito da .wrapper
dá o efeito de ser posicionado no canto superior direito da .navi
.
E aí está, #infoi
agora parece estar no canto superior direito de .navi
.
O resultado
O exemplo abaixo é resumido ao básico e contém alguns estilos mínimos.
/*
* 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>
Uma solução alternativa (grade)
Aqui está uma solução alternativa usando CSS Grid para posicionar o .navi
elemento com o #infoi
elemento na extrema direita. Eu usei as grid
propriedades detalhadas para deixar o mais claro possível.
: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>
Uma solução alternativa (sem invólucro)
Caso não possamos editar nenhum HTML, o que significa que não podemos adicionar um elemento wrapper, ainda podemos obter o efeito desejado.
Em vez de usar position: absolute
o #infoi
elemento, usaremos position: relative
. Isso nos permite reposicionar o #infoi
elemento de sua posição padrão abaixo do .navi
elemento. Com position: relative
podemos usar um top
valor negativo para movê-lo para cima de sua posição padrão, e um left
valor de 100%
menos alguns pixels, usando left: calc(100% - 52px)
, para posicioná-lo próximo ao lado direito.
/*
* 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
, use emoverflow: visible
vez disso.