จัดแนวภาพภายใน div ด้วยความสูงที่ตอบสนองได้


135

ฉันมีรหัสต่อไปนี้ซึ่งตั้งค่าคอนเทนเนอร์ที่มีความสูงที่เปลี่ยนแปลงตามความกว้างเมื่อเบราว์เซอร์มีขนาดใหม่ (เพื่อรักษาอัตราส่วนภาพสี่เหลี่ยมจัตุรัส)

HTML

<div class="responsive-container">
    <div class="dummy"></div>
    <div class="img-container">
        <IMG HERE>
    </div>
</div>

CSS

.responsive-container {
    position: relative;
    width: 100%;
    border: 1px solid black;
}

.dummy {
    padding-top: 100%; /* forces 1:1 aspect ratio */
}

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
}

ฉันจะจัดแนว IMG ในแนวตั้งภายในคอนเทนเนอร์ได้อย่างไร รูปภาพทั้งหมดของฉันมีความสูงที่หลากหลายและคอนเทนเนอร์ไม่สามารถมีความสูงคงที่ / ความสูงบรรทัดได้เนื่องจากมันตอบสนอง ... โปรดช่วยด้วย!


1
นี่คือโซลูชัน flexbox แบบง่าย ๆ : stackoverflow.com/a/31977476/3597276
Michael Benjamin

คำตอบ:


381

นี่คือเทคนิคองค์ประกอบแบบอินไลน์ชิดภายในเป็นผู้ปกครอง , แนวนอนและแนวตั้งในเวลาเดียวกัน:

การจัดตำแหน่งแนวตั้ง

1)ในวิธีการนี้เราสร้างinline-blockหลอก) องค์ประกอบเป็นครั้งแรก (หรือที่ผ่านมา) เด็กของ ( พ่อแม่และการตั้งค่าของheightคุณสมบัติการ100%ที่จะใช้ทั้งหมดความสูงของพ่อแม่

2)นอกจากนี้การเพิ่มvertical-align: middleจะช่วยให้องค์ประกอบแบบอินไลน์ (-block) อยู่ตรงกลางของพื้นที่บรรทัด ดังนั้นเราเพิ่มการประกาศ CSS นั้นลงในลูกคนแรกและองค์ประกอบของเรา ( ภาพ ) ทั้งคู่

3)ในที่สุดเพื่อที่จะลบตัวอักษร white space ระหว่างองค์ประกอบinline (-block)เราสามารถกำหนดขนาดตัวอักษรของparentเป็นศูนย์font-size: 0;ได้

หมายเหตุ:ฉันใช้เทคนิคการแทนที่รูปภาพของ Nicolas Gallagher ในเรื่องต่อไปนี้

ประโยชน์คืออะไร

  • ภาชนะ ( ผู้ปกครอง ) สามารถมีมิติแบบไดนามิก
  • ไม่จำเป็นต้องระบุขนาดขององค์ประกอบรูปภาพอย่างชัดเจน

  • เราสามารถใช้วิธีการนี้ในการจัด<div>องค์ประกอบในแนวตั้งเช่นกัน; ซึ่งอาจมีเนื้อหาแบบไดนามิก (ความสูงและ / หรือความกว้าง) แต่โปรดทราบว่าคุณต้องตั้งค่าfont-sizeคุณสมบัติของdivเพื่อแสดงข้อความภายในอีกครั้ง สาธิตออนไลน์

<div class="container">
    <div id="element"> ... </div>
</div>
.container {
    height: 300px;
    text-align: center;  /* align the inline(-block) elements horizontally */
    font: 0/0 a;         /* remove the gap between inline(-block) elements */
}

.container:before {    /* create a full-height inline block pseudo=element */
    content: ' ';
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    height: 100%;
}

#element {
    display: inline-block;
    vertical-align: middle;  /* vertical alignment of the inline element */
    font: 16px/1 Arial sans-serif;        /* <-- reset the font property */
}

ผลลัพธ์

จัดตำแหน่งองค์ประกอบในแนวตั้งในคอนเทนเนอร์

คอนเทนเนอร์ที่ตอบสนอง

ส่วนนี้จะไม่ตอบคำถามเนื่องจาก OP ทราบวิธีสร้างคอนเทนเนอร์ที่ตอบสนองแล้ว อย่างไรก็ตามฉันจะอธิบายวิธีการทำงาน

เพื่อที่จะทำให้ความสูงขององค์ประกอบคอนเทนเนอร์เปลี่ยนไปตามความกว้างของมัน(เทียบกับอัตราส่วนภาพ) เราสามารถใช้ค่าเปอร์เซ็นต์สำหรับpaddingคุณสมบัติด้านบน / ล่าง

ค่าเปอร์เซ็นต์ด้านบน padding / ล่างหรืออัตรากำไรขั้นต้นจะสัมพันธ์กับความกว้างของบล็อกที่มี

ตัวอย่างเช่น

.responsive-container {
  width: 60%;

  padding-top: 60%;    /* 1:1 Height is the same as the width */
  padding-top: 100%;   /* width:height = 60:100 or 3:5        */
  padding-top: 45%;    /* = 60% * 3/4 , width:height =  4:3   */
  padding-top: 33.75%; /* = 60% * 9/16, width:height = 16:9   */
}

นี่คือการสาธิตออนไลน์ แสดงความคิดเห็นออกจากด้านล่างและปรับขนาดแผงเพื่อดูผลกระทบ

นอกจากนี้เรายังสามารถใช้paddingคุณสมบัตินี้กับเด็กจำลองหรือองค์ประกอบ:before/ :afterหลอกเพื่อให้ได้ผลลัพธ์เดียวกัน แต่โปรดทราบว่าในกรณีนี้ค่าเปอร์เซ็นต์paddingจะสัมพันธ์กับความกว้างของ.responsive-containerตัวเอง

<div class="responsive-container">
  <div class="dummy"></div>
</div>
.responsive-container { width: 60%; }

.responsive-container .dummy {
  padding-top: 100%;    /*  1:1 square */
  padding-top: 75%;     /*  w:h =  4:3 */
  padding-top: 56.25%;  /*  w:h = 16:9 */
}

สาธิต # 1
การสาธิต # 2 (การใช้:afterองค์ประกอบหลอก)

การเพิ่มเนื้อหา

การใช้padding-topคุณสมบัติที่ทำให้เกิดช่องว่างขนาดใหญ่ที่ด้านบนหรือด้านล่างของเนื้อหาภายในภาชนะ

เพื่อที่จะแก้ไขปัญหาที่เรามีห่อเนื้อหาโดยองค์ประกอบห่อหุ้มเอาองค์ประกอบที่มาจากกระแสปกติเอกสารโดยใช้ตำแหน่งแน่นอนและในที่สุดก็ขยายเสื้อคลุม (bu ใช้top, right, bottomและleftคุณสมบัติ) เพื่อเติมเต็มพื้นที่ทั้งหมดของแม่ภาชนะ

ไปเลย:

.responsive-container {
  width: 60%;
  position: relative;
}

.responsive-container .wrapper {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

นี่คือการสาธิตออนไลน์


รวมเข้าด้วยกัน

<div class="responsive-container">
  <div class="dummy"></div>

  <div class="img-container">
    <img src="http://placehold.it/150x150" alt="">
  </div>
</div>
.img-container {
  text-align:center; /* Align center inline elements */
  font: 0/0 a;       /* Hide the characters like spaces */
}

.img-container:before {
  content: ' ';
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

.img-container img {
  vertical-align: middle;
  display: inline-block;
}

นี่คือการทำงาน DEMO

เห็นได้ชัดว่าคุณสามารถหลีกเลี่ยงการใช้::beforeองค์ประกอบหลอกสำหรับความเข้ากันได้ของเบราว์เซอร์และสร้างองค์ประกอบเป็นลูกคนแรกของ.img-container:

<div class="img-container">
    <div class="centerer"></div>
    <img src="http://placehold.it/150x150" alt="">
</div>
.img-container .centerer {
  display: inline-block;
  vertical-align: middle;
  height: 100%;
}

อัปเดตเดโม

การใช้max-*คุณสมบัติ

ในการเก็บภาพไว้ในกล่องในความกว้างต่ำกว่าคุณสามารถตั้งค่าmax-heightและmax-widthคุณสมบัติในภาพ:

.img-container img {
    vertical-align: middle;
    display: inline-block;
    max-height: 100%;  /* <-- Set maximum height to 100% of its parent */
    max-width: 100%;   /* <-- Set maximum width to 100% of its parent */
}

นี่คือการสาธิตการปรับปรุง


1
สวัสดี Hashem ขอบคุณมากสำหรับคำตอบของคุณ - มันใช้งานได้ดีเหมือนเวทมนตร์สำหรับเบราว์เซอร์เดสก์ท็อปแม้เมื่อปรับขนาดเป็นความกว้างที่เล็กลง แต่น่าเสียดายที่ภาพปรากฏออกจากตำแหน่งใต้ div div บนมือถือ (Android v2.3.5) มีความคิดใดเกี่ยวกับการแก้ไขปัญหานี้บ้าง?
user1794295

3
@ user1794295 ฉันทดสอบซอนี้บนอุปกรณ์ android สามเครื่องที่มี android v2.3 (Galaxy S II, Galaxy Note, Motorola Droid 4) ผ่าน browserstack.com ทุกอย่างทำงานได้ตามที่คาดไว้คุณสามารถค้นหาผลลัพธ์ได้ที่นี่: browserstack.com/scurrencys / … . โปรดระบุภาพหน้าจอหรือทดสอบปัญหาของคุณโดยเฉพาะ ฉันจะช่วยเท่าที่จะทำได้
Hashem Qolami

1
สวัสดีนี่คือสกรีนช็อตบางส่วน: browserstack.com/sc Screenshots/… - อย่างที่คุณเห็นด้วยอุปกรณ์ขนาดเล็ก (เช่น Xperia, LG Nexus 4) ภาพที่ปรากฏด้านล่างภาชนะ ... เกิดอะไรขึ้น!
user1794295

3
@HashemQolami นี่คือสิ่ง CSS ที่น่าทึ่งที่สุดตั้งแต่ฉันเริ่มสร้างเว็บไซต์ :)
Alexander Solonik

1
ขอบคุณสำหรับfont-size: 0;!
Johannes Liebermann

47

ด้วย flexbox นี้ง่าย:

ซอ

เพียงเพิ่มสิ่งต่อไปนี้ลงในคอนเทนเนอร์รูปภาพ:

.img-container {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    display: flex; /* add */
    justify-content: center; /* add to align horizontal */
    align-items: center; /* add to align vertical */
}

2
โซลูชันนี้ใช้งานได้และดูสง่างามยิ่งขึ้นในกรณีของฉัน CSS3 Flex ยอดเยี่ยมมาก!
Daniel Bonnell

2
มันใช้งานไม่ได้ใน Safari :( ฉันเดาว่าปัญหาจะยืดหยุ่น
yennefer

1
@yennefer สำหรับ Safari ใช้-webkit-คำนำหน้าหรือลองใช้ไลบรารี่เช่น prefixfree.js :)
QUB3X

สิ่งนี้ไม่ทำงานเมื่อความสูงของคอนเทนเนอร์ตอบสนอง (เป็นเปอร์เซ็นต์)
jenlampton

1
โซลูชั่นที่สมบูรณ์แบบ!
Nirus

16

ใช้ css นี้ตามที่คุณมีมาร์กอัปแล้ว:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
}

.img-container > img {
  margin-top:-50%;
  margin-left:-50%;  
}

นี่คือ JsBin ที่ใช้งานได้: http://jsbin.com/ihilUnI/1/edit

โซลูชันนี้ใช้งานได้กับภาพสี่เหลี่ยมจัตุรัสเท่านั้น (เนื่องจากค่าเปอร์เซ็นต์บนสุดของระยะขอบขึ้นอยู่กับความกว้างของคอนเทนเนอร์ไม่ใช่ความสูง) สำหรับภาพขนาดสุ่มคุณสามารถทำสิ่งต่อไปนี้:

.img-container {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* add browser-prefixes */
}

วิธีแก้ไขปัญหา JsBin ที่ทำงาน: http://jsbin.com/ihilUnI/2/edit


ขออภัยไม่ทำงานสำหรับฉัน - นี่เป็นเพียงการลดขนาดของภาพให้เหลือความกว้างครึ่งหนึ่งของคอนเทนเนอร์
user1794295

2
ฉันไม่เห็นว่าจะเกิดอะไรขึ้นกับ CSS ที่ฉันกล่าวถึง โปรดให้ตัวอย่างการทำงานที่ฉันสามารถเห็นเพื่อให้ฉันสามารถปรับปรุงคำตอบของฉัน PS: ผมยังให้วิธีอื่น :)
Tibos

11

คุณสามารถจัดกึ่งกลางภาพทั้งแนวนอนและแนวตั้งโดยใช้margin: autoและการจัดตำแหน่งแบบสัมบูรณ์ นอกจากนี้:

  1. เป็นไปได้ที่จะทิ้งมาร์กอัพพิเศษโดยใช้องค์ประกอบหลอก
  2. เป็นไปได้ที่จะแสดงส่วนตรงกลางของภาพขนาดใหญ่โดยใช้ค่าลบซ้าย, บน, ขวาและล่าง

.responsive-container {
  margin: 1em auto;
  min-width: 200px;       /* cap container min width */
  max-width: 500px;       /* cap container max width */
  position: relative;     
  overflow: hidden;       /* crop if image is larger than container */
  background-color: #CCC; 
}
.responsive-container:before {
  content: "";            /* using pseudo element for 1:1 ratio */
  display: block;
  padding-top: 100%;
}
.responsive-container img {
  position: absolute;
  top: -999px;            /* use sufficiently large number */
  bottom: -999px;
  left: -999px;
  right: -999px;
  margin: auto;           /* center horizontally and vertically */
}
<p>Note: images are center-cropped on &lt;400px screen width.
  <br>Open full page demo and resize browser.</p>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/400/sports/9/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/400/200/sports/8/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/400/sports/7/">
</div>
<div class="responsive-container">
  <img src="http://lorempixel.com/200/200/sports/6/">
</div>


ขอบคุณ! ภาชนะที่ตอบสนองของคุณ img css เป็นคนเดียวที่ทำงานให้ฉัน
Diogo Garcia

4

ลองอันนี้

  .responsive-container{
          display:table;
  }
  .img-container{
          display:table-cell;
          vertical-align: middle;
   }

ขออภัยสิ่งนี้ไม่ทำงานฉันคิดว่าเพราะฉัน.img-containerอยู่ในตำแหน่งที่แน่นอน - นี่เป็นสิ่งจำเป็นเพื่อรักษาอัตราส่วนสี่เหลี่ยมจัตุรัส / ความสูงแบบไดนามิก
user1794295

2

นี่คือเทคนิคที่ช่วยให้คุณสามารถจัดศูนย์กลางเนื้อหาใด ๆ ได้ทั้งแนวตั้งและแนวนอน!

โดยพื้นฐานแล้วคุณเพียงแค่ต้องการสองคอนเทนเนอร์และตรวจสอบให้แน่ใจว่าองค์ประกอบของคุณตรงตามเกณฑ์ต่อไปนี้

ภาชนะนอก:

  • ควรมี display: table;

ภาชนะภายใน:

  • ควรมี display: table-cell;
  • ควรมี vertical-align: middle;
  • ควรมี text-align: center;

กล่องเนื้อหา:

  • ควรมี display: inline-block;

หากคุณใช้เทคนิคนี้เพียงแค่เพิ่มภาพของคุณ (พร้อมกับเนื้อหาอื่น ๆ ที่คุณต้องการไปด้วย) ลงในกล่องเนื้อหา

การสาธิต :

body {
    margin : 0;
}

.outer-container {
    position : absolute;
    display: table;
    width: 100%;
    height: 100%;
    background: #ccc;
}

.inner-container {
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}

.centered-content {
    display: inline-block;
    background: #fff;
    padding : 12px;
    border : 1px solid #000;
}

img {
   max-width : 120px;
}
<div class="outer-container">
   <div class="inner-container">
     <div class="centered-content">
        <img src="https://i.stack.imgur.com/mRsBv.png" />
     </div>
   </div>
</div>

ดูซอนี้ !


2

ฉันเจอกระทู้นี้ในการค้นหาโซลูชันที่:

  • ใช้ 100% ของความกว้างของภาพที่กำหนด
  • รักษาอัตราส่วนภาพ
  • ทำให้ภาพอยู่ในแนวตั้งตรงกลาง
  • ทำงานในเบราว์เซอร์ที่ไม่รองรับการทำงานแบบยืดหยุ่น

การทดสอบวิธีแก้ปัญหาบางอย่างที่โพสต์ไว้ด้านบนฉันไม่พบวิธีที่ตรงกับเกณฑ์ทั้งหมดนี้ดังนั้นฉันจึงรวบรวมวิธีง่ายๆนี้ซึ่งอาจเป็นประโยชน์สำหรับคนอื่นที่ต้องทำแบบเดียวกัน:

.container {
  width: 30%;
  float: left;
  border: 1px solid turquoise;
  margin-right: 3px;
  margin-top: 3px;
}

.container:last-of-kind {
  margin-right: 0px;
}

.image-container {
  position: relative;
  overflow: hidden;
  padding-bottom: 70%;
  /* this is the desired aspect ratio */
  width: 100%;
}

.image-container img {
  position: absolute;
  /* the following 3 properties center the image on the vertical axis */
  top: 0;
  bottom: 0;
  margin: auto;
  /* uses image at 100% width (also meaning it's horizontally center) */
  width: 100%;
}
<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

<div class="container">
  <div class="image-container">
    <img src="http://placehold.it/800x800" class="img-responsive">
  </div>
</div>

ตัวอย่างการทำงานบนJSFiddle


0

ลอง

html

<div class="responsive-container">
     <div class="img-container">
         <IMG HERE>
     </div>
</div>

CSS

.img-container {
    position: absolute;
    top: 0;
    left: 0;
height:0;
padding-bottom:100%;
}
.img-container img {
width:100%;
}

0

รหัส html

<div class="image-container"> <img src=""/> </div>

รหัส css

img
{
  position: relative;
  top: 50%;
  transform: translateY(-50%);
 }

ขณะที่ข้อมูลโค้ดนี้คือการต้อนรับและอาจให้ความช่วยเหลือบางส่วนก็จะได้รับการปรับปรุงอย่างมากถ้ามันรวมถึงคำอธิบายของวิธีการที่มันอยู่ในคำถาม หากไม่มีคำตอบของคุณจะมีคุณค่าทางการศึกษาน้อยลง - โปรดจำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตไม่ใช่เพียงแค่คนที่ถามตอนนี้! โปรดแก้ไขคำตอบของคุณเพื่อเพิ่มคำอธิบายและระบุข้อ จำกัด และสมมติฐานที่ใช้
Toby Speight

0

สร้างอีก div แล้วเพิ่มทั้ง 'dummy' และ 'img-container' ใน div

ทำ HTML และ CSS ดังนี้

html , body {height:100%;}
.responsive-container { height:100%; display:table; text-align:center; width:100%;}
.inner-container {display:table-cell; vertical-align:middle;}
<div class="responsive-container">
    <div class="inner-container">
		<div class="dummy">Sample</div>
		<div class="img-container">
			Image tag
		</div>
	</div>	
</div>

แทนที่จะเป็น 100% สำหรับ 'responsive-container' คุณสามารถกำหนดความสูงที่คุณต้องการได้

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