วิธีซ้อนทับ div หนึ่งกับ div อื่น


958

ฉันต้องการความช่วยเหลือเกี่ยวกับการซ้อนทับคนใดคนหนึ่งมากกว่าบุคคลอื่นdivdiv

รหัสของฉันมีลักษณะเช่นนี้:

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

แต่น่าเสียดายที่ผมไม่สามารถรังdiv#infoiหรือภายในครั้งแรกimgdiv.navi

มันต้องแยกกันสองอันdivดังที่แสดงไว้ แต่ฉันต้องรู้ว่าฉันจะวางส่วนdiv#infoiบนdiv.naviและด้านขวาสุดdiv.naviได้อย่างไร


ไม่ใช่กรณีในคำถามนี้ แต่ถ้าคุณมี div หนึ่งใน div อื่น div ในอาจจะถูกปกปิดทั้งหมดหรือบางส่วนเนื่องจากoverflow: hiddenใช้overflow: visibleแทน
Christophe Roussy

คำตอบ:


1241

#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>

ผมจะแนะนำเกี่ยวกับการเรียนรู้และองค์ประกอบของเด็กด้วยposition: relativeposition: absolute


3
ขอบคุณ alex สำหรับความช่วยเหลือของคุณ แต่สิ่งที่ฉันกำลังค้นหาตอนนี้คือเมื่อฉันปรับขนาดหน้าต่างและลากให้เล็กลงรูปภาพข้อมูลของฉันไม่ได้อยู่กับพ่อแม่ของมัน โดยทั่วไปต้องการให้มันย้ายไปพร้อมกับ div parent และอยู่ในตำแหน่งเดิมมากแม้ว่าหน้าจอจะถูกปรับขนาดบ้าง
tonyf

2
@tonsils:คำแนะนำโดยalexควรให้ผลลัพธ์ที่ต้องการดังนั้นจะต้องมีสิ่งอื่นที่ทำให้เกิดปัญหาที่คุณอธิบาย คุณสามารถให้ตัวอย่างรหัส (HTML + CSS) แก่เราเพื่อให้เราช่วยได้ไหม
Erik TöyräSilfverswärd

9
absoluteองค์ประกอบที่มีตำแหน่งอยู่ในตำแหน่งจะสัมพันธ์กับองค์ประกอบหลักที่อยู่ใกล้ที่สุด ( position:absolute|relative|fixed) อย่างชัดเจน ชี้แจงเพิ่มเติมเพียงแค่ ... jsfiddle.net/p5jkc8gz
xandercoded

สิ่งนี้สามารถปรับเปลี่ยนได้ ในสถานการณ์ของฉันฉันไม่จำเป็นต้อง #navi เป็นอันดับสูงสุด: 0 เหลือ: 0 และเป็นกรณีทั่วไปหากคุณมีรหัส HTML ก็จะถูกวางตราบเท่าที่มีการแยกวิเคราะห์ต้นไม้ HTML ดังนั้นในกรณีนี้คำจำกัดความที่ไม่จำเป็น
Fabricio PH

402

โซลูชันที่ได้รับการยอมรับนั้นใช้งานได้ดี แต่ IMO ไม่มีคำอธิบายว่าทำไมมันจึงใช้งานได้ ตัวอย่างด้านล่างนี้ถูกต้มลงไปจนถึงข้อมูลพื้นฐานและแยก CSS สำคัญออกจาก CSS สไตล์ที่ไม่เกี่ยวข้อง เป็นโบนัสฉันยังได้รวมคำอธิบายโดยละเอียดเกี่ยวกับวิธีการวางตำแหน่ง CSS

TLDR; ถ้าคุณต้องการเพียงรหัสเลื่อนลงไปผลที่ตามมา

ปัญหา

มีสองแยกพี่น้ององค์ประกอบและเป้าหมายคือการวางตำแหน่งองค์ประกอบที่สอง (กับidของinfoi) ดังนั้นมันจะปรากฏขึ้นภายในองค์ประกอบก่อนหน้า (หนึ่งที่มีclassของnavi) โครงสร้าง HTML ไม่สามารถเปลี่ยนแปลงได้

โซลูชันที่เสนอ

เพื่อให้บรรลุผลที่ต้องการเรากำลังจะย้ายหรือตำแหน่งองค์ประกอบที่สองซึ่งเราจะเรียกมันจึงปรากฏอยู่ในองค์ประกอบแรกซึ่งเราจะเรียก#infoi .naviโดยเฉพาะที่เราต้องการที่จะอยู่ในตำแหน่งที่มุมบนขวาของ#infoi.navi

ความรู้ที่จำเป็นในตำแหน่ง CSS

CSS มีคุณสมบัติหลายอย่างสำหรับองค์ประกอบการวางตำแหน่ง position: staticโดยค่าเริ่มต้นองค์ประกอบทั้งหมดที่มี ซึ่งหมายความว่าองค์ประกอบจะถูกจัดวางตามลำดับในโครงสร้าง HTML โดยมีข้อยกเว้นเล็กน้อย

อื่น ๆ ที่positionมีค่าrelative, absolute, และsticky fixedโดยการตั้งค่าองค์ประกอบpositionให้เป็นหนึ่งในค่าอื่น ๆ เหล่านี้ตอนนี้เป็นไปได้ที่จะใช้การรวมกันของสี่คุณสมบัติต่อไปนี้เพื่อวางตำแหน่งองค์ประกอบ:

  • top
  • right
  • bottom
  • left

กล่าวอีกนัยหนึ่งการตั้งค่าposition: absoluteเราสามารถเพิ่มtop: 100pxองค์ประกอบพิกเซล 100 จากด้านบนของหน้า ในทางกลับกันหากเราตั้งค่าbottom: 100pxองค์ประกอบจะถูกวางตำแหน่ง 100 พิกเซลจากด้านล่างของหน้า

นี่คือสิ่งที่ผู้มาใหม่ CSS หลงทาง -position: absoluteมีกรอบของการอ้างอิง ในตัวอย่างข้างต้นกรอบอ้างอิงคือbodyองค์ประกอบ position: absoluteด้วยtop: 100pxหมายความว่าองค์ประกอบอยู่ในตำแหน่ง 100 พิกเซลจากด้านบนของbodyองค์ประกอบ

กรอบของการอ้างอิงตำแหน่งหรือบริบทตำแหน่งสามารถเปลี่ยนแปลงได้โดยการตั้งค่าpositionขององค์ประกอบหลักที่จะคุ้มค่ากว่าใด ๆ อื่น ๆ position: staticนั่นคือเราสามารถสร้างบริบทตำแหน่งใหม่โดยการให้องค์ประกอบหลัก:

  • position: relative;
  • position: absolute;
  • position: sticky;
  • position: fixed;

ตัวอย่างเช่นหากมีการ<div class="parent">ให้position: relativeองค์ประกอบองค์ประกอบย่อยจะใช้<div class="parent">บริบทของตำแหน่ง หากองค์ประกอบย่อยได้รับposition: absoluteและtop: 100pxองค์ประกอบจะถูกวางตำแหน่ง 100 พิกเซลจากด้านบนของ<div class="parent">องค์ประกอบเพราะ<div class="parent">ตอนนี้บริบทบริบทตำแหน่ง

อีกปัจจัยที่ต้องระวังคือการเรียงลำดับสแต็กหรือองค์ประกอบที่ซ้อนกันในทิศทาง z สิ่งที่ต้องรู้ที่นี่คือลำดับสแต็กขององค์ประกอบคือตามค่าเริ่มต้นที่กำหนดโดยการย้อนกลับของลำดับในโครงสร้าง HTML ลองพิจารณาตัวอย่างต่อไปนี้:

<body>
  <div>Bottom</div>
  <div>Top</div>
</body>

ในตัวอย่างนี้หาก<div>องค์ประกอบทั้งสองอยู่ในตำแหน่งเดียวกันในหน้า<div>Top</div>องค์ประกอบจะครอบคลุม<div>Bottom</div>องค์ประกอบนั้น เนื่องจาก<div>Top</div>มา<div>Bottom</div>ในโครงสร้าง HTML จึงมีลำดับการซ้อนสูงกว่า

ลำดับการสแต็กสามารถเปลี่ยนแปลงได้ด้วย CSS โดยใช้คุณสมบัติz-indexหรือorder

เราสามารถเพิกเฉยต่อลำดับการซ้อนในปัญหานี้เนื่องจากโครงสร้าง HTML ตามธรรมชาติขององค์ประกอบหมายถึงองค์ประกอบที่เราต้องการให้ปรากฏขึ้นtopหลังจากองค์ประกอบอื่น

ดังนั้นกลับไปที่ปัญหาที่เกิดขึ้น - เราจะใช้บริบทตำแหน่งเพื่อแก้ปัญหานี้

การแก้ไขปัญหา

ตามที่ระบุไว้ข้างต้นเป้าหมายของเราคือการจัดวาง#infoiองค์ประกอบเพื่อให้ปรากฏภายใน.naviองค์ประกอบ ในการทำเช่นนี้เราจะ.naviรวม#infoiองค์ประกอบและในองค์ประกอบใหม่<div class="wrapper">เพื่อให้เราสามารถสร้างบริบทตำแหน่งใหม่

<div class="wrapper">
  <div class="navi"></div>
  <div id="infoi"></div>
</div>

แล้วสร้างบริบทตำแหน่งใหม่โดยให้.wrapperposition: relative

.wrapper {
  position: relative;
}

ด้วยบริบทตำแหน่งใหม่นี้เราสามารถวางตำแหน่งภายใน#infoi .wrapperขั้นแรกให้ช่วยให้เราไปอยู่ในตำแหน่งอย่างแน่นอนใน#infoiposition: absolute#infoi.wrapper

จากนั้นเพิ่มtop: 0และright: 0วางตำแหน่ง#infoiองค์ประกอบที่มุมขวาบน โปรดจำไว้ว่าเนื่องจาก#infoiองค์ประกอบนี้ใช้.wrapperเป็นบริบทตำแหน่งจึงจะอยู่ในมุมขวาบนของ.wrapperองค์ประกอบ

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

เพราะ.wrapperเป็นเพียงภาชนะสำหรับ.naviตำแหน่ง#infoiที่มุมขวาบนของให้ผลของการถูกวางในที่มุมบนขวาของ.wrapper.navi

และมีเรามีมันตอนนี้ดูเหมือนจะเป็นที่มุมขวาบนของ#infoi.navi

ผลลัพธ์

ตัวอย่างด้านล่างนี้ถูกนำไปใช้เป็นพื้นฐานและมีการกำหนดสไตล์ขั้นต่ำ

โซลูชันสำรอง (กริด)

นี่คือโซลูชันทางเลือกโดยใช้ CSS Grid เพื่อจัดวาง.naviองค์ประกอบกับ#infoiองค์ประกอบทางด้านขวาสุด ฉันใช้gridคุณสมบัติverbose เพื่อให้ชัดเจนที่สุด

โซลูชันสำรอง (ไม่มีกระดาษห่อ)

ในกรณีที่เราไม่สามารถแก้ไข HTML ใด ๆ ได้หมายความว่าเราไม่สามารถเพิ่มองค์ประกอบของ wrapper ได้ แต่เรายังสามารถสร้างเอฟเฟกต์ที่ต้องการได้

แทนการใช้position: absoluteในองค์ประกอบที่เราจะใช้#infoi position: relativeสิ่งนี้ช่วยให้เราสามารถเปลี่ยนตำแหน่ง#infoiองค์ประกอบจากตำแหน่งเริ่มต้นด้านล่าง.naviองค์ประกอบ ด้วยposition: relativeเราสามารถใช้topค่าลบเพื่อเลื่อนขึ้นจากตำแหน่งเริ่มต้นและleftค่า100%ลบด้วยพิกเซลสองสามใช้left: calc(100% - 52px)เพื่อวางตำแหน่งใกล้ด้านขวา


29
นี่เป็นรายการ IMO ที่มีประโยชน์ที่สุดเพราะอธิบายว่าทำไมจึงใช้งานได้!
Bret Weinraub

20
นี่อาจเป็นคำอธิบายที่ดีที่สุดเกี่ยวกับวิธีการวางตำแหน่งที่ฉันเคยเห็น กระชับ แต่ลึกพอที่จะทำให้ถูกต้อง
Marcel

2
เหมือนกันกับคุณภาพของคำตอบ คำอธิบายที่ชัดเจนที่สุดที่ฉันเคยเห็น
ลุย Hatler

2
นี่เป็นคำตอบที่ดีโดยเฉพาะอย่างยิ่งสำหรับผู้มาใหม่ใน css
Ali Ezzat Odeh

2
รุ่งโรจน์สำหรับคำอธิบาย
Joey587

111

โดยใช้divกับรูปแบบz-index:1;และposition: absolute;คุณสามารถแสดงข้อมูลของคุณในที่อื่นdivdiv

z-indexกำหนดลำดับซึ่งกอง 'div' กองกับที่สูงขึ้นz-indexจะปรากฏในหน้าของ div z-indexที่มีลดลง โปรดทราบว่าคุณสมบัตินี้ใช้งานได้กับองค์ประกอบในตำแหน่งเท่านั้น


5
คุณสามารถให้ตัวอย่างได้หรือไม่
Fabricio PH

3
หมายเหตุเกี่ยวกับองค์ประกอบตำแหน่งเป็นสิ่งสำคัญ
Lawrence Dol

คำตอบนี้ไม่สมบูรณ์จนต้องมีโพสต์ทั้งหมดเพื่ออธิบายว่าทำไม ค้นหาบริบทที่ซ้อนกัน
Bojidar Stanchev

39

ข้อมูลจำเพาะGrid CSSใหม่มอบโซลูชันที่ยอดเยี่ยมกว่า การใช้position: absoluteอาจนำไปสู่การทับซ้อนหรือปรับขนาดปัญหาในขณะที่ Grid จะช่วยคุณจากการแฮ็ก CSS ที่สกปรก

ตัวอย่าง Grid Overlay ที่น้อยที่สุด:

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;
}

แค่นั้นแหละ. หากคุณไม่ได้สร้างสำหรับ Internet Explorer รหัสของคุณอาจทำงานได้ดีที่สุด


4
นี่ควรเป็นคำตอบที่ดีที่สุด
อินไลน์

1
คำตอบที่เหนือกว่า คำตอบที่เลือกควรได้รับการประเมินอีกครั้ง
AbdulG

โซลูชั่นที่สมบูรณ์แบบ
Deniz da King

24

ต่อไปนี้เป็นวิธีแก้ไขปัญหาอย่างง่าย 100% ตาม CSS "ความลับ" คือการใช้display: inline-blockในองค์ประกอบเสื้อคลุม vertical-align: bottomในภาพเป็นสับที่จะเอาชนะ 4px padding ที่เบราว์เซอร์บางเพิ่มหลังจากองค์ประกอบ

คำแนะนำ : ถ้าองค์ประกอบก่อน wrapper เป็นแบบอินไลน์พวกเขาสามารถวางซ้อนกันได้ ในกรณีนี้คุณสามารถ "ห่อกระดาษห่อ" ภายในภาชนะที่มีdisplay: block- 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>


20

นี่คือสิ่งที่คุณต้องการ:

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>


9

ฉันไม่ได้เป็น coder หรือผู้เชี่ยวชาญใน CSS มากนัก แต่ฉันยังคงใช้ความคิดของคุณในการออกแบบเว็บของฉัน ฉันได้ลองใช้วิธีแก้ปัญหาต่างกันเช่นกัน:

#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>

แน่นอนว่าจะมีเสื้อคลุมรอบตัวทั้งคู่ คุณสามารถควบคุมตำแหน่งของ div เมนูซึ่งจะแสดงภายใน div header ด้วยระยะขอบซ้ายและตำแหน่งบนสุด คุณยังสามารถตั้งค่าเมนู div ให้เลื่อนไปทางขวาหากต้องการ


0

นี่คือตัวอย่างง่ายๆที่จะนำเอฟเฟกต์ภาพซ้อนทับพร้อมไอคอนโหลดไปที่อีก 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>

ลองที่นี่: http://jsbin.com/fotozolucu/edit?html,css,outout

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.