Cómo superponer un div sobre otro div

958

Necesito ayuda para superponer a un individuo divsobre otro individuo div.

Mi código se ve así:

<div class="navi"></div>
<div id="infoi">
    <img src="info_icon2.png" height="20" width="32"/>
</div>

Lamentablemente no puedo anidar el div#infoio el img, dentro del primero div.navi.

Tiene que ser dos divs separados como se muestra, pero necesito saber cómo podría colocar el div#infoisobre div.naviy hacia el lado más a la derecha y centrado en la parte superior del div.navi.

tonyf
fuente
No es el caso en esta pregunta, pero si tiene un div dentro de otro div, el div interno puede estar enmascarado total o parcialmente debido a overflow: hidden, use overflow: visibleen su lugar.
Christophe Roussy

Respuestas:

1242

#container {
  width: 100px;
  height: 100px;
  position: relative;
}
#navi,
#infoi {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
#infoi {
  z-index: 10;
}
<div id="container">
  <div id="navi">a</div>
  <div id="infoi">
    <img src="https://appharbor.com/assets/images/stackoverflow-logo.png" height="20" width="32" />b
  </div>
</div>

Sugeriría aprender sobre position: relativey elementos secundarios con position: absolute.

alex
fuente
3
gracias alex por tu ayuda, pero lo que estoy encontrando ahora es que cuando cambio el tamaño de mi ventana y la arrastro para que sea más pequeña, mi imagen de información no se queda con su div principal. Básicamente quiero que se mueva con el div padre y se mantenga prácticamente en la misma posición a pesar de que la pantalla ha cambiado de tamaño un poco.
tonyf
2
@tonsils: las instrucciones de alex deberían darle el resultado deseado, por lo que debe haber algo más que cause el problema que usted describe. ¿Podría proporcionarnos una muestra del código (HTML + CSS) para que podamos ayudarlo?
Erik Töyrä Silfverswärd
99
absoluteLos elementos posicionados correctamente se colocan en relación con su position:absolute|relative|fixedelemento padre más cercano ( ). solo una aclaración más ... jsfiddle.net/p5jkc8gz
xandercoded
Dependiendo del caso, esto se puede adaptar. En mi situación, no necesitaba #navi para estar arriba: 0 a la izquierda: 0, y como un caso general Si tiene código HTML, estará situado siempre que se analice el árbol HTML. Entonces, tal vez en este caso esa definición no sea necesaria.
Fabricio PH
403

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 idde infoi), para que aparezca dentro del elemento anterior (el que tiene un classde 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 #infoipara que aparezca dentro del primer elemento, al que llamaremos .navi. Específicamente, queremos #infoiubicarnos 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 positionvalores son relative, absolute, sticky, y fixed. Al establecer un elemento positionen uno de estos otros valores, ahora es posible usar una combinación de las siguientes cuatro propiedades para posicionar el elemento:

  • top
  • right
  • bottom
  • left

En otras palabras, mediante la configuración position: absolute, podemos agregar top: 100pxpara colocar el elemento a 100 píxeles desde la parte superior de la página. Por el contrario, si configuramos bottom: 100pxel 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: absolutetiene un marco de referencia. En el ejemplo anterior, el marco de referencia es elbodyelemento. position: absolutecontop: 100pxsignifica que el elemento se coloca a 100 píxeles desde la parte superior delbodyelemento.

El marco de referencia de la posición, o el contexto de la posición, puede modificarse configurando positionun 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: absolutey 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.

El orden de apilamiento se puede cambiar con CSS utilizando las propiedades z-indexo 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 topviene 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 #infoielemento para que aparezca dentro del .navielemento. Para hacer esto, envolveremos los elementos .naviy #infoien 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 .wrappera position: relative.

.wrapper {
  position: relative;
}

Con este nuevo contexto de posición, podemos posicionarnos #infoidentro .wrapper. Primero, da #infoiun position: absolute, permitiéndonos posicionarnos #infoiabsolutamente .wrapper.

Luego agregue top: 0y right: 0para colocar el #infoielemento en la esquina superior derecha. Recuerde, debido a que el #infoielemento está utilizando .wrappercomo contexto de posición, estará en la parte superior derecha del .wrapperelemento.

#infoi {
  position: absolute;
  top: 0;
  right: 0;
}

Debido a que .wrapperes simplemente un contenedor para .navi, el posicionamiento #infoien la esquina superior derecha de .wrapperda el efecto de estar ubicado en la esquina superior derecha de .navi.

Y ahí lo tenemos, #infoiahora 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.

Una solución alternativa (cuadrícula)

Aquí hay una solución alternativa usando CSS Grid para posicionar el .navielemento con el #infoielemento en el extremo derecho. He usado las gridpropiedades detalladas para hacerlo lo más claro posible.

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: absoluteen el #infoielemento, usaremos position: relative. Esto nos permite reposicionar el #infoielemento desde su posición predeterminada debajo del .navielemento. Con position: relativepodemos usar un topvalor negativo para moverlo hacia arriba desde su posición predeterminada, y un leftvalor de 100%menos unos pocos píxeles, usando left: calc(100% - 52px), para colocarlo cerca del lado derecho.

Brett DeWoody
fuente
29
Esta es la entrada más útil de la OMI porque explica por qué funciona.
Bret Weinraub
20
Esta es probablemente la mejor explicación de cómo funciona el posicionamiento que he visto hasta ahora. Conciso, pero lo suficientemente profundo como para hacerlo bien.
Marcel
2
Lo mismo ocurre con la calidad de la respuesta. La explicación más clara que he visto.
Wade Hatler
2
Esta es una gran respuesta, especialmente para los recién llegados en CSS
Ali Ezzat Odeh
2
Felicitaciones por la explicación
Joey587
111

Al usar un divestilo con z-index:1;y position: absolute;puede superponer su diven cualquier otro div.

z-indexdetermina el orden en que los divs se 'apilan'. Un div con un mayor z-indexaparecerá delante de un div con un menor z-index. Tenga en cuenta que esta propiedad solo funciona con elementos posicionados .

Hari Thakur
fuente
55
¿Puede dar un ejemplo?
Fabricio PH
3
La nota sobre los elementos posicionados es crítica.
Lawrence Dol
Esta respuesta es tan incompleta que necesita una publicación completa para explicar por qué. Busque contextos de apilamiento.
Bojidar Stanchev
39

La nueva especificación Grid CSS proporciona una solución mucho más elegante. El uso position: absolutepuede provocar superposiciones o problemas de escala, mientras que Grid lo salvará de hacks CSS sucios.

Ejemplo de superposición de cuadrícula mínima:

HTML

<div class="container">
  <div class="content">This is the content</div>
  <div class="overlay">Overlay - must be placed under content in the HTML</div>
</div>

CSS

.container {
  display: grid;
}

.content, .overlay {
  grid-area: 1 / 1;
}

Eso es. Si no compila para Internet Explorer, su código probablemente funcionará.

ja0nz
fuente
44
Esta debería ser la mejor respuesta.
línea el
1
Respuesta superior La respuesta seleccionada debe ser reevaluada.
AbdulG
Solución perfecta
Deniz da King
24

Aquí sigue una solución simple 100% basada en CSS. El "secreto" es usar el display: inline-blockelemento en el contenedor. El vertical-align: bottomen la imagen es un truco para superar el relleno de 4px que algunos navegadores agregan después del elemento.

Consejo : si el elemento antes del contenedor está en línea, pueden terminar anidados. En este caso, puede "envolver el envoltorio" dentro de un contenedor con display: block, por lo general, un buen y viejo div.

.wrapper {
    display: inline-block;
    position: relative;
}

.hover {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 188, 212, 0);
    transition: background-color 0.5s;
}

.hover:hover {
    background-color: rgba(0, 188, 212, 0.8);
    // You can tweak with other background properties too (ie: background-image)...
}

img {
    vertical-align: bottom;
}
<div class="wrapper">
    <div class="hover"></div>
    <img src="http://placehold.it/450x250" />
</div>

Tuco
fuente
20

Esto es lo que necesitas:

function showFrontLayer() {
  document.getElementById('bg_mask').style.visibility='visible';
  document.getElementById('frontlayer').style.visibility='visible';
}
function hideFrontLayer() {
  document.getElementById('bg_mask').style.visibility='hidden';
  document.getElementById('frontlayer').style.visibility='hidden';
}
#bg_mask {
  position: absolute;
  top: 0;
  right: 0;  bottom: 0;
  left: 0;
  margin: auto;
  margin-top: 0px;
  width: 981px;
  height: 610px;
  background : url("img_dot_white.jpg") center;
  z-index: 0;
  visibility: hidden;
} 

#frontlayer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: 70px 140px 175px 140px;
  padding : 30px;
  width: 700px;
  height: 400px;
  background-color: orange;
  visibility: hidden;
  border: 1px solid black;
  z-index: 1;
} 


</style>
<html>
  <head>
    <META HTTP-EQUIV="EXPIRES" CONTENT="-1" />

  </head>
  <body>
    <form action="test.html">
      <div id="baselayer">

        <input type="text" value="testing text"/>
        <input type="button" value="Show front layer" onclick="showFrontLayer();"/> Click 'Show front layer' button<br/><br/><br/>

        Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text
        Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text
        Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing textsting text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text Testing text
        <div id="bg_mask">
          <div id="frontlayer"><br/><br/>
            Now try to click on "Show front layer" button or the text box. It is not active.<br/><br/><br/>
            Use position: absolute to get the one div on top of another div.<br/><br/><br/>
            The bg_mask div is between baselayer and front layer.<br/><br/><br/>
            In bg_mask, img_dot_white.jpg(1 pixel in width and height) is used as background image to avoid IE browser transparency issue;<br/><br/><br/>
            <input type="button" value="Hide front layer" onclick="hideFrontLayer();"/>
          </div>
        </div>
      </div>
    </form>
  </body>
</html>

DhavalThakor
fuente
9

No soy muy codificador ni experto en CSS, pero sigo usando tu idea en mis diseños web. También probé diferentes resoluciones:

#wrapper {
  margin: 0 auto;
  width: 901px;
  height: 100%;
  background-color: #f7f7f7;
  background-image: url(images/wrapperback.gif);
  color: #000;
}
#header {
  float: left;
  width: 100.00%;
  height: 122px;
  background-color: #00314e;
  background-image: url(images/header.jpg);
  color: #fff;
}
#menu {
  float: left;
  padding-top: 20px;
  margin-left: 495px;
  width: 390px;
  color: #f1f1f1;
}
<div id="wrapper">
  <div id="header">
    <div id="menu">
      menu will go here
    </div>
  </div>
</div>

Por supuesto, habrá un envoltorio alrededor de ambos. Puede controlar la ubicación del menú div que se mostrará dentro del encabezado div con márgenes izquierdos y posiciones superiores. También puede configurar el menú div para que flote a la derecha si lo desea.

Muhammad Ahsan
fuente
0

Aquí hay un ejemplo simple para traer un efecto de superposición con un ícono de carga sobre otro div.

<style>
    #overlay {
        position: absolute;
        width: 100%;
        height: 100%;
        background: black url('icons/loading.gif') center center no-repeat; /* Make sure the path and a fine named 'loading.gif' is there */
        background-size: 50px;
        z-index: 1;
        opacity: .6;
    }
    .wraper{
        position: relative;
        width:400px;  /* Just for testing, remove width and height if you have content inside this div */
        height:500px; /* Remove this if you have content inside */
    }
</style>

<h2>The overlay tester</h2>
<div class="wraper">
    <div id="overlay"></div>
    <h3>Apply the overlay over this div</h3>
</div>

Pruébelo aquí: http://jsbin.com/fotozolucu/edit?html,css,output

Nishad Up
fuente