Trung tâm hình ảnh quá khổ trong Div


175

Tôi đã cố gắng sắp xếp làm thế nào để căn giữa một hình ảnh quá khổ trong một div chỉ bằng css.

Chúng tôi đang sử dụng bố cục chất lỏng, vì vậy chiều rộng của các thùng chứa hình ảnh thay đổi theo chiều rộng của trang (chiều cao của div là cố định). Hình ảnh nằm trong một div, xác định giá trị hình hộp bên trong để xuất hiện như thể bạn đang xem qua trang ở hình ảnh.

Hình ảnh đã được kích thước để lấp đầy div xung quanh ở giá trị rộng nhất có thể của nó (thiết kế có max-widthgiá trị).

Nó khá dễ thực hiện nếu hình ảnh nhỏ hơn div xung quanh:

margin-left: auto;
margin-right: auto;
display: block; 

Nhưng khi hình ảnh lớn hơn div, nó chỉ bắt đầu ở cạnh trái và nằm ở giữa bên phải (chúng tôi đang sử dụng overflow: hidden).

Chúng tôi có thể chỉ định một width=100%, nhưng các trình duyệt thực hiện một công việc tệ hại là thay đổi kích thước hình ảnh và các trung tâm thiết kế web xung quanh hình ảnh chất lượng cao.

Bất kỳ ý tưởng về trung tâm hình ảnh để overflow:hiddencắt đều cả hai cạnh?


2
Bạn đã bao giờ giải quyết vấn đề này @Tom chưa? Tôi đang chạy vào cùng một vấn đề tại thời điểm này. :)
ctrlplusb

Tôi giả sử rằng chiều rộng hình ảnh của bạn khác nhau.
otherDewi

Câu trả lời:


365

Hãy thử một cái gì đó như thế này. Điều này sẽ tập trung bất kỳ yếu tố lớn nào ở giữa theo chiều dọc và chiều ngang đối với cha mẹ của nó, bất kể cả hai kích thước của chúng.

.parent {
    position: relative;
    overflow: hidden;
    //optionally set height and width, it will depend on the rest of the styling used
}

.child {
    position: absolute;
    top: -9999px;
    bottom: -9999px;
    left: -9999px;
    right: -9999px;
    margin: auto;

}

4
tuyệt vời: điều này làm việc với bất kỳ yếu tố. ngay cả với video html 5 ... cảm ơn!
taseenb

3
Theo tôi hiểu điều này: nó hoạt động vì nó tạo ra một phần tử (hy vọng) lớn hơn hình ảnh (2 * 9999px x 2 * 9999px) và căn giữa hình ảnh bên trong phần tử đó (lề: tự động). Vì vậy, miễn là hình ảnh không vượt quá 2 * 9999px thì nó sẽ hoạt động.
Michael Krupp

16
Tại sao không sử dụng -100%cho đầu / phải / dưới / trái? Với điều đó, container có thể có bất kỳ chiều rộng.
Simon

15
Vâng, tôi cũng đã trải qua -100%vấn đề này rồi ^^. Btw: nếu bạn thêm min-widthmin-heightcác 100%bạn về cơ bản có được một background-size: cover;hành vi với các thẻ hình ảnh -> jsfiddle
Simon

3
@HarrisonPowers Vâng, phụ huynh phải có chiều cao tất nhiên, cho dù đó là cố định hay năng động. Nó cũng sẽ hoạt động nếu một số nội dung khác đang lấp đầy div khiến nó có chiều cao (ví dụ như văn bản).
hyounis

162

Đây là một Q cũ, nhưng một giải pháp hiện đại không có flexbox hoặc vị trí hoạt động tuyệt đối như thế này.

margin-left: 50%;
transform: translateX(-50%);

Vậy tại sao nó hoạt động?
Thoạt nhìn có vẻ như chúng ta dịch chuyển 50% sang phải và sau đó 50% sang trái. Điều đó sẽ dẫn đến sự thay đổi bằng không, vậy thì sao?
Nhưng 50% không giống nhau, vì bối cảnh rất quan trọng. Nếu bạn sử dụng các đơn vị tương đối, một lề sẽ được tính bằng tỷ lệ phần trăm chiều rộng của phần tử cha , trong khi biến đổi sẽ là 50% so với phần tử tương tự .

Chúng tôi có tình huống này trước khi chúng tôi thêm CSS

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
       +-----------------------------------------------------------+
       | Element E                                                 |
       +-----------------------------------------------------------+
       |                                           |
       +-------------------------------------------+

Với phong cách thêm vào, margin-left: 50%chúng tôi có

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
       |                     +-----------------------------------------------------------+
       |                     | Element E                                                 |
       |                     +-----------------------------------------------------------+
       |                     |                     |
       +---------------------|---------------------+
       |========= a ========>|

       a is 50% width of P

Và sự transform: translateX(-50%)dịch chuyển về bên trái

       +-------------------------------------------+
       | Parent element P of E                     |
       |                                           |
+-----------------------------------------------------------+
| Element E                 |                               |
+-----------------------------------------------------------+
|<============ b ===========|                      |
       |                    |                      |
       +--------------------|----------------------+
       |========= a =======>|

       a is 50% width of P
       b is 50% width of E

Thật không may, điều này chỉ hoạt động đối với định tâm ngang vì tính toán tỷ lệ phần trăm lề luôn luôn tương đối với chiều rộng. Tức là không chỉ margin-leftmargin-right, mà còn margin-topmargin-bottomđược tính theo chiều rộng.

Khả năng tương thích trình duyệt sẽ không có vấn đề: https://caniuse.com/#feat=transforms2d


Nó không hoạt động đối với căn chỉnh dọc (khi .inner có chiều cao lớn hơn .outer)
cronfy

1
@cronfy Số theo chiều dọc nó sẽ không hoạt động, vì margin-top: 50%sẽ là 50% chiều rộng . không phải chiều cao như mong muốn.
yunzen

2
đó là giải pháp tao nhã nhất
Souhaieb Besbes

tìm kiếm một giải pháp trong một thời gian, tốt nhất, đơn giản nhất; Chúc mừng
lauWM

2
Đây là phép thuật thuần túy. Cảm ơn bạn! Hoạt động hoàn hảo trong Safari và Chrome (có thêm -webkit-transform: translateX(-50%);biện pháp tốt)
Nick Schneble 17/12/18

22

Đặt một div lớn bên trong div, chính giữa và trung tâm hình ảnh bên trong div đó.

Điều này tập trung vào nó theo chiều ngang:

HTML:

<div class="imageContainer">
  <div class="imageCenterer">
    <img src="http://placekitten.com/200/200" />
  </div>
</div>

CSS:

.imageContainer {
  width: 100px;
  height: 100px;
  overflow: hidden;
  position: relative;
}
.imageCenterer {
  width: 1000px;
  position: absolute;
  left: 50%;
  top: 0;
  margin-left: -500px;
}
.imageCenterer img {
  display: block;
  margin: 0 auto;
}

Bản trình diễn: http://jsfiddle.net/Guffa/L9BnL/

Để căn giữa nó theo chiều dọc, bạn có thể sử dụng tương tự cho div bên trong, nhưng bạn sẽ cần chiều cao của hình ảnh để đặt nó hoàn toàn bên trong nó.


Điều này đã kết thúc với cạnh trái của hình ảnh được căn giữa trong "imageContainer". Như tôi đã nhận xét ở trên, div container hình ảnh của chúng tôi là chiều rộng chất lỏng và chiều cao cố định.
Tom

1
@Tom: Nếu tôi xóa widthcài đặt trên vùng chứa, nó sẽ là chiều rộng của cha mẹ và hình ảnh được căn giữa ngay cả khi trang hẹp hơn hình ảnh, tức là càng nhiều cạnh trái như cạnh phải sẽ bị ẩn : jsfiddle.net/Guffa/L9BnL/2
Guffa

Cảm ơn đã truyền cảm hứng. Tôi sử dụng vị trí: tương đối cho .imageCenter. Bằng cách này, tôi không cần vị trí: tương đối cho vùng chứa cha.
dùng3153298

Có rất nhiều mánh khóe thông minh cho câu hỏi này và tất cả chúng đều có nhược điểm. Một số công việc "tốt hơn" nhưng không dễ hiểu chút nào. Giải pháp này có ý nghĩa hoàn hảo, hình ảnh đang được tập trung bình thường trong một div rộng hơn đang được cắt. Nó cảm thấy sai, nhưng nó chắc chắn hoạt động mà không vi phạm các quy luật vật lý web. Tôi đã chọn tùy chọn này hơn một số thủ thuật rất khó hiểu khác, ngay cả khi nó cảm thấy hơi bẩn.
Radley Sustaire

9

Muộn trò chơi, nhưng tôi thấy phương pháp này cực kỳ trực quan. https://codepen.io/adamchenwei/pen/BRNxJr

CSS

.imageContainer {
  border: 1px black solid;

  width: 450px;
  height: 200px;
  overflow: hidden;
}
.imageHolder {
  border: 1px red dotted;

  height: 100%;
  display:flex;
  align-items: center;
}
.imageItself {
  height: auto;
  width: 100%;
  align-self: center;

}

HTML

<div class="imageContainer">
  <div class="imageHolder">
    <img class="imageItself" src="http://www.fiorieconfetti.com/sites/default/files/styles/product_thumbnail__300x360_/public/fiore_viola%20-%202.jpg" />
  </div>
</div>

3
Đẹp! Nó có thể được đơn giản hóa, quá. Thủ thuật được thực hiện bởi display: flextrên thùng chứa cha mẹ và align-self: centertrên hình ảnh. Đây là phiên bản được tối ưu hóa: codepen.io/anon/pen/dWKyey
caiosm1005

5

Không sử dụng chiều rộng hoặc chiều cao rõ ràng cho thẻ hình ảnh. Thay vào đó, mã nó:

      max-width:100%;
      max-height:100%;

ví dụ: http://jsfiddle.net/xwrvxser/1/


1
Điều này sau đó để lại không gian xung quanh hình ảnh mà tôi tin rằng họ đang cố gắng tránh.
Eoin

3

Tôi là một fan hâm mộ lớn của việc tạo hình ảnh làm nền của div / nút - sau đó bạn chỉ có thể sử dụng background-position: centerthuộc tính để căn giữa nó bất kể kích thước màn hình


9
Đây không phải là một cách có thể truy cập sử dụng hình ảnh. Nó có thể hoạt động tốt cho hình ảnh trang trí, nhưng bất kỳ hình ảnh nào là thông tin cần văn bản thay thế.
dùng2532030

0

Chiều rộng và chiều cao chỉ là ví dụ:

parentDiv{
    width: 100px;
    height: 100px;
    position:relative; 
}
innerDiv{
    width: 200px;
    height: 200px;
    position:absolute; 
    margin: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

Nó phải hoạt động cho bạn nếu bên trái và trên cùng của div cha mẹ của bạn không phải là trên cùng và bên trái của cửa sổ màn hình của bạn. Nó làm việc cho tôi.


Dường như không tạo ra sự khác biệt. Không chắc chắn nếu nó có bất cứ điều gì do thực tế là chiều rộng là chất lỏng, trong khi chiều cao được cố định trên div chính là gì.
Tom

2
Kỹ thuật này hoạt động nếu hình ảnh nhỏ hơn container.
otherDewi

0

Tôi thấy đây là một giải pháp thanh lịch hơn, không có flex:

.wrapper {
    overflow: hidden;
}
.wrapper img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* height: 100%; */ /* optional */
}

0

Dựa trên câu trả lời tuyệt vời của @ yunzen:

Tôi đoán nhiều người đang tìm kiếm chủ đề này đang cố gắng sử dụng một hình ảnh lớn làm hình nền "anh hùng", ví dụ như trên trang chủ. Trong trường hợp này, họ thường muốn văn bản xuất hiện trên hình ảnh và để nó thu nhỏ lại trên thiết bị di động.

Đây là CSS hoàn hảo cho một hình nền như vậy (sử dụng nó trên <img>thẻ):

/* Set left edge of inner element to 50% of the parent element */
margin-left: 50%;

/* Move to the left by 50% of own width */
transform: translateX(-50%);

/* Scale image...(101% - instead of 100% - avoids possible 1px white border on left of image due to rounding error */
width: 101%;

/* ...but don't scale it too small on mobile devices - adjust this as needed */
min-width: 1086px;

/* allow content below image to appear on top of image */
position: absolute;
z-index: -1;

/* OPTIONAL - try with/without based on your needs */
top: 0;

/* OPTIONAL - use if your outer element containing the img has "text-align: center" */
left: 0;

-1

Một tùy chọn bạn có thể sử dụng là object-fit: covernó hoạt động hơi giống background-size: cover. Thêm về đối tượng phù hợp .

bỏ qua tất cả các mã bên dưới, đó chỉ là bản demo.

Chìa khóa ở đây là bạn cần đặt hình ảnh bên trong một trình bao bọc và cung cấp cho nó các thuộc tính sau.

.wrapper img {
  height: 100%;
  width: 100%;
  object-fit: cover;
}

Tôi đã tạo một bản demo bên dưới nơi bạn thay đổi chiều cao / chiều rộng của trình bao bọc và xem trong khi chơi. Hình ảnh sẽ luôn được căn giữa theo chiều dọc và chiều ngang. Nó sẽ chiếm 100% chiều rộng và chiều cao cha mẹ của nó, và sẽ không bị kéo dài / đè bẹp. Điều này có nghĩa là tỷ lệ khung hình của hình ảnh được duy trì. Thay đổi được áp dụng bằng cách phóng to / thu nhỏ thay thế.

Nhược điểm duy nhất object-fitlà nó không hoạt động trên IE11.

// for demo only
const wrapper = document.querySelector('.wrapper');
const button = document.querySelector('button');
const widthInput = document.querySelector('.width-input');
const heightInput = document.querySelector('.height-input');


const resizeWrapper = () => {
  wrapper.style.width = widthInput.value + "px";
  wrapper.style.height = heightInput.value + "px";
}

button.addEventListener("click", resizeWrapper);
.wrapper {
  overflow: hidden;
  max-width: 100%;
  margin-bottom: 2em;
  border: 1px solid red;
}

.wrapper img {
  display: block;
  height: 100%;
  width: 100%;
  object-fit: cover;
}
<div class="wrapper">
  <img src="https://i.imgur.com/DrzMS8i.png">
</div>


<!-- demo only -->
<lable for="width">
  Width: <input name="width" class='width-input'>
</lable>
<lable for="height">
  height: <input name="height" class='height-input'>
</lable>
<button>change size!</button>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.