La solución aceptada funciona muy bien, pero IMO carece de una explicación de por qué funciona. El siguiente ejemplo se reduce a lo básico y separa el CSS importante del CSS de estilo no relevante. Como beneficio adicional, también he incluido una explicación detallada de cómo funciona el posicionamiento CSS.
TLDR; Si solo desea el código, desplácese hacia abajo hasta El resultado .
El problema
Hay dos elementos separados, hermanos, y el objetivo es posicionar el segundo elemento (con un id
de infoi
), para que aparezca dentro del elemento anterior (el que tiene un class
de navi
). La estructura HTML no se puede cambiar.
Solución propuesta
Para lograr el resultado deseado, vamos a mover, o posicionar, el segundo elemento, al que llamaremos #infoi
para que aparezca dentro del primer elemento, al que llamaremos .navi
. Específicamente, queremos #infoi
ubicarnos en la esquina superior derecha de .navi
.
Posición de CSS Conocimiento requerido
CSS tiene varias propiedades para posicionar elementos. Por defecto, todos los elementos son position: static
. Esto significa que el elemento se posicionará de acuerdo con su orden en la estructura HTML, con pocas excepciones.
Los otros position
valores son relative
, absolute
, sticky
, y fixed
. Al establecer un elemento position
en uno de estos otros valores, ahora es posible usar una combinación de las siguientes cuatro propiedades para posicionar el elemento:
En otras palabras, mediante la configuración position: absolute
, podemos agregar top: 100px
para colocar el elemento a 100 píxeles desde la parte superior de la página. Por el contrario, si configuramos bottom: 100px
el elemento se colocaría a 100 píxeles desde la parte inferior de la página.
Aquí es donde se pierden muchos recién llegados de CSS :position: absolute
tiene un marco de referencia. En el ejemplo anterior, el marco de referencia es elbody
elemento. position: absolute
contop: 100px
significa que el elemento se coloca a 100 píxeles desde la parte superior delbody
elemento.
El marco de referencia de la posición, o el contexto de la posición, puede modificarse configurando position
un elemento padre en cualquier valor distinto deposition: static
. Es decir, podemos crear un nuevo contexto de posición dando un elemento padre:
position: relative;
position: absolute;
position: sticky;
position: fixed;
Por ejemplo, si <div class="parent">
se da un elemento position: relative
, cualquier elemento hijo usa el <div class="parent">
como su contexto de posición. Si se diera un elemento secundario position: absolute
y top: 100px
, el elemento se colocaría a 100 píxeles de la parte superior del <div class="parent">
elemento, porque <div class="parent">
ahora es el contexto de posición.
El otro factor a tener en cuenta es el orden de la pila , o cómo se apilan los elementos en la dirección z. Lo que debe saber aquí es que el orden de los elementos está, por defecto, definido por el reverso de su orden en la estructura HTML. Considere el siguiente ejemplo:
<body>
<div>Bottom</div>
<div>Top</div>
</body>
En este ejemplo, si los dos <div>
elementos se colocaran en el mismo lugar de la página, el <div>Top</div>
elemento cubriría el <div>Bottom</div>
elemento. Como <div>Top</div>
viene después <div>Bottom</div>
en la estructura HTML, tiene un orden de apilamiento más alto.
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>
El orden de apilamiento se puede cambiar con CSS utilizando las propiedades z-index
o order
.
Podemos ignorar el orden de apilamiento en este tema, ya que la estructura HTML natural de los elementos significa que el elemento en el que queremos aparecer top
viene después del otro elemento.
Entonces, volviendo al problema en cuestión, usaremos el contexto de posición para resolver este problema.
La solución
Como se indicó anteriormente, nuestro objetivo es posicionar el #infoi
elemento para que aparezca dentro del .navi
elemento. Para hacer esto, envolveremos los elementos .navi
y #infoi
en un nuevo elemento <div class="wrapper">
para que podamos crear un nuevo contexto de posición.
<div class="wrapper">
<div class="navi"></div>
<div id="infoi"></div>
</div>
Luego cree un nuevo contexto de posición dando .wrapper
a position: relative
.
.wrapper {
position: relative;
}
Con este nuevo contexto de posición, podemos posicionarnos #infoi
dentro .wrapper
. Primero, da #infoi
un position: absolute
, permitiéndonos posicionarnos #infoi
absolutamente .wrapper
.
Luego agregue top: 0
y right: 0
para colocar el #infoi
elemento en la esquina superior derecha. Recuerde, debido a que el #infoi
elemento está utilizando .wrapper
como contexto de posición, estará en la parte superior derecha del .wrapper
elemento.
#infoi {
position: absolute;
top: 0;
right: 0;
}
Debido a que .wrapper
es simplemente un contenedor para .navi
, el posicionamiento #infoi
en la esquina superior derecha de .wrapper
da el efecto de estar ubicado en la esquina superior derecha de .navi
.
Y ahí lo tenemos, #infoi
ahora parece estar en la esquina superior derecha de .navi
.
El resultado
El siguiente ejemplo se reduce a lo básico y contiene un estilo mínimo.
/*
* 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 solución alternativa (cuadrícula)
Aquí hay una solución alternativa usando CSS Grid para posicionar el .navi
elemento con el #infoi
elemento en el extremo derecho. He usado las grid
propiedades detalladas para hacerlo lo más claro posible.
: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 solución alternativa (sin envoltura)
En el caso de que no podamos editar ningún HTML, lo que significa que no podemos agregar un elemento contenedor, aún podemos lograr el efecto deseado.
En lugar de usar position: absolute
en el #infoi
elemento, usaremos position: relative
. Esto nos permite reposicionar el #infoi
elemento desde su posición predeterminada debajo del .navi
elemento. Con position: relative
podemos usar un top
valor negativo para moverlo hacia arriba desde su posición predeterminada, y un left
valor de 100%
menos unos pocos píxeles, usando left: calc(100% - 52px)
, para colocarlo cerca del lado derecho.
/*
* 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
, useoverflow: visible
en su lugar.