CSS: Đặt chiều rộng / chiều cao dưới dạng Phần trăm trừ đi pixel


479

Tôi đang cố gắng tạo một số lớp CSS có thể sử dụng lại để có tính nhất quán hơn và ít lộn xộn hơn trên trang web của mình và tôi bị mắc kẹt khi cố gắng tiêu chuẩn hóa một thứ tôi sử dụng thường xuyên.

Tôi có một thùng chứa <div>mà tôi không muốn đặt chiều cao cho (vì nó sẽ thay đổi tùy thuộc vào vị trí của nó trên trang web) và bên trong nó là một tiêu đề <div>và sau đó là danh sách các mục không được sắp xếp , tất cả đều được áp dụng CSS họ

Nó trông rất giống như thế này:

Widget

Tôi muốn các danh sách không có thứ tự để đưa lên các phòng còn lại trong các thùng chứa <div>, biết rằng phần đầu <div>18pxcao. Tôi chỉ không biết làm thế nào để xác định chiều cao của danh sách là "kết quả của 100%âm 18px".

Tôi đã thấy câu hỏi này được hỏi trong một vài bối cảnh khác về SO, nhưng tôi nghĩ rằng nó sẽ đáng để hỏi lại cho trường hợp cụ thể của tôi. Có ai có lời khuyên nào trong tình huống này không?


6
Đặt lề? __
kennytm

@KennyTM, tôi giả sử bạn đang đề xuất tôi đặt một lề trên vào danh sách không có thứ tự của tôi, giả sử, 17px. Nhưng điều này chỉ đẩy toàn bộ danh sách xuống; Nó không làm cho nó co lại để ở trong container. Về cơ bản, chiều cao hiện tại của nó được duy trì, nhưng nó chỉ bị đẩy xuống 17px. Điều này không giải quyết được vấn đề của tôi, nhưng tôi nghĩ đó là một bước đi đúng hướng bởi vì tôi đã thấy các phương pháp trực tuyến khác sử dụng kỹ thuật này.
MegaMatt

Tôi chỉ giải quyết vấn đề này trong câu hỏi của tôi, tôi đã đăng ở đây. stackoverflow.com/a/10420387/340947
Steven Lu

sao chép CSS
200_success

Câu trả lời:


895

Tôi nhận ra đây là một bài viết cũ, nhưng cho rằng nó chưa được đề xuất nên đề cập rằng nếu bạn đang viết cho các trình duyệt tuân thủ CSS3, bạn có thể sử dụng calc:

height: calc(100% - 18px);

Điều đáng lưu ý là hiện tại không phải tất cả các trình duyệt đều hỗ trợ hàm calc3 (CSS3) tiêu chuẩn, do đó, việc triển khai các phiên bản cụ thể của trình duyệt có thể được yêu cầu như sau:

/* Firefox */
height: -moz-calc(100% - 18px);
/* WebKit */
height: -webkit-calc(100% - 18px);
/* Opera */
height: -o-calc(100% - 18px);
/* Standard */
height: calc(100% - 18px);

5
Vâng, đó là bình thường trong thời gian này.
Levi Botelho

1
Hoạt động với tôi trong IE10 và Chrome 27. Thưa ông, là người hùng đáng sợ của tôi!
BrainSlugs83

3
@LeviBotelho Xấu quá. Không có không gian xung quanh nhà điều hành.
người dùng

20
Ngoài ra, nếu bạn sử dụng Ít, bạn nên biên dịch một tệp tốt hơn lessc --strict-math=onđể không đánh giá biểu thức bên trong calc- chỉ là vấn đề tôi gặp phải và mất rất nhiều thời gian (kể từ Ít 2.0.0)
Dmitry Wojciechowski

34
Lưu ý rằng không gian xung quanh dấu trừ là không bắt buộc: 100%-18px, 100%- 18px, và 100% -18pxđã không làm việc trong các trình duyệt tôi thử nghiệm với.
nisetama

71

Đối với một chút cách tiếp cận khác nhau, bạn có thể sử dụng một cái gì đó như thế này trong danh sách:

position: absolute;
top: 18px;
bottom: 0px;
width: 100%;

Điều này hoạt động miễn là container mẹ có position: relative;


1
cảm ơn người đàn ông thùng chứa cha mẹ đang position: relative;vấp ngã tôi.
gthmb

Đối với những người có thể tự hỏi như tôi: vị trí phải absoluteở trong thùng chứa trẻ em, nó không thể được relative.
Greg

Tiếp tục (xin lỗi): Tuy nhiên, cha mẹ chỉ cần định vị (cũng có thể như absolutevậy) và nó cũng cần được đặt thành 100% chiều cao.
Greg

1
Thật không may, nó không hoạt động trên Safari iOS 8. (Đã kiểm tra OK trên trình duyệt chứng khoán Android 4.1 và FF 34 tiêu chuẩn) :-(
Greg

Điều này có thể hoạt động trong một số trường hợp, nhưng cũng có thể gây ra một số rắc rối, vì các phần tử được định vị tuyệt đối được xóa khỏi luồng bình thường, xem stackoverflow.com/a/12821537/4173303 .
Barshe Weis

26

Tôi sử dụng Jquery cho việc này

function setSizes() {
   var containerHeight = $("#listContainer").height();
   $("#myList").height(containerHeight - 18);
}

sau đó tôi liên kết thay đổi kích thước cửa sổ để tính lại nó bất cứ khi nào cửa sổ trình duyệt được thay đổi kích thước (nếu kích thước của trình thay đổi với thay đổi kích thước cửa sổ)

$(window).resize(function() { setSizes(); });

12
@puffpio, Chắc chắn JS là một cách để thực hiện điều này trong từng trường hợp. Nhưng như tôi đã nói, tôi đang cố gắng tạo CSS chung, để được áp dụng trên nhiều trang (tình cờ kế thừa từ một trang chính). Vì vậy, tôi không muốn sử dụng JS. Nhưng cảm ơn vì câu trả lời.
MegaMatt

7
Đừng đặt phong cách của bạn vào JavaScript.
Greg

8
@greg, nó sẽ giúp nếu CSS có một số tính năng hữu ích hơn. Một số điều bạn phải thực hiện hack là vô lý.
Jonathan.

1
@puffpio Giải pháp đẹp thật. Nhưng các sự kiện ràng buộc trên cửa sổ không phải là một giải pháp tốt cho tôi. Nếu trang của tôi có 3-4 phần tử trở lên như vậy, tôi phải cập nhật chiều cao và chiều rộng của mỗi phần tử trong trình xử lý thay đổi kích thước cửa sổ. Điều này sẽ chậm hơn một chút so với giải pháp CSS.
sachinjain024

1
"Đừng đặt xyz của bạn vào JavaScript" giống như nói "không hỗ trợ 80% thị trường trình duyệt".
Beejor

16

Đừng xác định chiều cao là phần trăm, chỉ cần đặt top=0bottom=0, như thế này:

#div {
   top: 0; bottom: 0;
   position: absolute;
   width: 100%;
}

Bạn có thể giải thích tại sao không đặt chiều cao thành phần trăm không?
Shrikant Sharat

@ShrikantSharat Đây là một phần của thông số định dạng trực quan cho các yếu tố được định vị tuyệt đối. Giải pháp này tận dụng khả năng 5., "'chiều cao" là' tự động ',' trên cùng 'và' dưới cùng 'không phải là' tự động ', sau đó các giá trị' tự động 'cho' lề trên 'và' lề dưới 'được đặt về 0 và giải quyết 'chiều cao' ". Trình duyệt có thể tính toán chiều cao của phần tử bởi vì nó biết khoảng cách từ đỉnh và đáy của phần tử mẹ cần bao xa.
Ross Allen

Điều này dường như không hoạt động, ít nhất là trong Firefox. Ngay cả với tất cả các phần tử cha được đặt thành height:100%display:block. Nếu không nó sẽ là một giải pháp rất thanh lịch. Thật thú vị, margin:autocũng không tập trung vào một đối tượng có chiều rộng cố định theo chiều dọc, mặc dù nó hoạt động tốt theo chiều ngang.
Beejor

8

Giả định chiều cao tiêu đề 17px

Danh sách css:

height: 100%;
padding-top: 17px;

Tiêu đề css:

height: 17px;
float: left;
width: 100%;

Đúng, đó là những gì tôi đã nhận được.
dclowd9901

1
Điều đó đã không làm việc khá tốt như tôi đã hy vọng. Danh sách không theo thứ tự của tôi đang được bắt đầu bên dưới div tiêu đề đó. Div tiêu đề đang chiếm không gian trong vùng chứa, do đó, việc đặt padding-top 17px vào danh sách sẽ đẩy nó xuống 17px từ vị trí đã có trong hình trên, chứ không phải 17px từ đỉnh div container. Đây là một bức ảnh về những gì tôi nhận được với CSS được đưa ra trong câu trả lời ở trên: i41.tinypic.com/mcuk1x.jpg . Mặc dù vậy, tôi đánh giá cao nỗ lực này và nếu có điều gì bạn nghĩ là tôi đang thiếu, xin vui lòng cho tôi biết. Btw, tôi có tràn: tự động trong danh sách không có thứ tự là tốt.
MegaMatt

2
Sẽ dễ dàng hơn rất nhiều khi khắc phục sự cố này nếu bạn đăng css thực tế để chúng tôi có thể thấy chính xác những tương tác đang diễn ra. Một điều khác bạn có thể thử là lề trên âm tính trên ul của bạn. ul { margin-top: -17px; }
ghoppe

7
  1. Sử dụng lề âm trên phần tử bạn muốn trừ đi pixel. (yếu tố mong muốn)
  2. Tạo overflow:hidden;thành phần tử chứa
  3. Chuyển sang overflow:auto;phần tử mong muốn.

Nó làm việc cho tôi!


3
Điều này làm việc như một cơ duyên đối với tôi (tôi thậm chí không cần thay đổi tràn). Giải pháp tuyệt vời, cảm ơn bạn!
Aaj

1
Hoàn toàn tuyệt vời! Rất thích tìm hiểu về giải pháp "CSS calc" phổ biến, nhưng điều này đơn giản hơn nhiều và có hỗ trợ trình duyệt rộng hơn. Lợi nhuận âm trong hoàn hảo!
Simon Steinberger

Đây là một giải pháp rất thanh lịch và tương thích. Nhược điểm chính là yếu tố phải có chiều cao cố định. Nếu không, bạn cần phải sử dụng JS hoặc calc()tập trung vào nó trong thời gian chạy. Nhưng đối với nhiều trường hợp thì đây không phải là một vấn đề. Một lưu ý khác là việc sử dụng nhiều giá trị âm cho lề, phần đệm và độ lệch có thể gây nhầm lẫn khi gỡ lỗi mã sau này, vì vậy hãy cố gắng giữ mọi thứ đơn giản.
Beejor

5

Hãy thử kích thước hộp. Đối với danh sách:

height: 100%;
/* Presuming 10px header height */
padding-top: 10px;
/* Firefox */
-moz-box-sizing: border-box;
/* WebKit */
-webkit-box-sizing: border-box;
/* Standard */
box-sizing: border-box;

Đối với tiêu đề:

position: absolute;
left: 0;
top: 0;
height: 10px;

Tất nhiên, thùng chứa cha mẹ nên có cái gì đó như:

position: relative;

3

Một cách khác để đạt được cùng một mục tiêu: hộp flex . Biến hộp chứa thành hộp uốn cột và sau đó bạn có toàn quyền cho phép một số thành phần có kích thước cố định (hành vi mặc định) hoặc lấp đầy / thu nhỏ xuống không gian chứa (với flex-grow: 1 và flex- co lại: 1).

#wrap {        
  display:flex;
  flex-direction:column;
}
.extendOrShrink {
  flex-shrink:1;
  flex-grow:1;
  overflow:auto;
}

Xem https://jsfiddle.net/2Lmodwxk/ (cố gắng mở rộng hoặc giảm cửa sổ để nhận thấy hiệu quả)

Lưu ý: bạn cũng có thể sử dụng thuộc tính tốc ký:

   flex:1 1 auto;

Tôi tin rằng đây có thể là câu trả lời tốt nhất hiện nay bởi vì nó có nghĩa là không phải chỉ định chiều cao đã đặt cho div tiêu đề (18px trong câu hỏi ban đầu của tôi) và điều đó có nghĩa là không phải trừ đi những thứ như đệm và lề. Không đặt pixel và mọi thứ đều tự chăm sóc.
MegaMatt

2

Tôi đã thử một số câu trả lời khác, và không ai trong số họ làm việc theo cách tôi muốn. Tình huống của chúng tôi rất giống nhau khi chúng tôi có một tiêu đề cửa sổ và cửa sổ có thể thay đổi kích thước với hình ảnh trong thân cửa sổ. Chúng tôi muốn khóa tỷ lệ khung hình của thay đổi kích thước mà không cần thêm vào tính toán để tính kích thước cố định của tiêu đề và vẫn có hình ảnh lấp đầy thân cửa sổ.

Dưới đây tôi đã tạo một đoạn rất đơn giản cho thấy những gì chúng tôi đã làm dường như hoạt động tốt cho tình huống của chúng tôi và phải tương thích trên hầu hết các trình duyệt.

Trên phần tử cửa sổ của chúng tôi, chúng tôi đã thêm một lề 20px, góp phần định vị so với các phần tử khác trên màn hình, nhưng không đóng góp vào "kích thước" của cửa sổ. Sau đó, tiêu đề cửa sổ được định vị tuyệt đối (loại bỏ nó khỏi luồng của các phần tử khác, do đó, nó sẽ không làm cho các phần tử khác như danh sách không được sắp xếp được thay đổi) và phần trên cùng của nó được đặt ở vị trí -20px đặt tiêu đề bên trong lề của cửa sổ. Cuối cùng, phần tử ul của chúng ta được thêm vào cửa sổ và chiều cao có thể được đặt thành 100%, điều này sẽ khiến nó lấp đầy cơ thể của cửa sổ (không bao gồm lề).

*,*:before,*:after
{
  box-sizing: border-box;
}

.window
{
  position: relative;
  top: 20px;
  left: 50px;
  margin-top: 20px;
  width: 150px;
  height: 150px;
}

.window-header
{
  position: absolute;
  top: -20px;
  height: 20px;
  border: 2px solid black;
  width: 100%;
}

ul
{
  border: 5px dashed gray;
  height: 100%;
}
<div class="window">
  <div class="window-header">Hey this is a header</div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
</div>


1

Cảm ơn, tôi đã giải quyết vấn đề của tôi với sự giúp đỡ của bạn, điều chỉnh nó một chút vì tôi muốn div 100% chiều rộng 100% (chiều cao ít hơn của thanh dưới cùng) và không cuộn trên cơ thể (không có hack / ẩn thanh cuộn).

Đối với CSS:

 html{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 body{
  position:relative;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 div.adjusted{
  position:absolute;width:auto;height:auto;left:0px;right:0px;top:0px;bottom:36px;margin:0px;border:0px;padding:0px;
 }
 div.the_bottom_bar{
  width:100%;height:31px;margin:0px;border:0px;padding:0px;
}

Đối với HTML:

<body>
<div class="adjusted">
 // My elements that go on dynamic size area
 <div class="the_bottom_bar">
  // My elements that goes on bottom bar (fixed heigh of 31 pixels)
 </div>  
</div>  

Điều đó đã tạo ra mánh khóe, ồ đúng rồi, tôi đặt một giá trị lớn hơn trên div.được điều chỉnh cho đáy so với chiều cao của thanh dưới cùng, nếu không thì thanh cuộn dọc xuất hiện, tôi điều chỉnh thành giá trị gần nhất.

Sự khác biệt đó là do một trong các yếu tố trên vùng động đang thêm một lỗ dưới cùng mà tôi không biết làm cách nào để thoát khỏi ... đó là thẻ video (HTML5), xin lưu ý tôi đặt thẻ video đó bằng css này ( vì vậy không có lý do gì để nó tạo ra một lỗ dưới cùng, nhưng nó có):

 video{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

Objetive: Có một video chiếm 100% trình duyệt (và thay đổi kích thước linh hoạt khi trình duyệt được thay đổi kích thước, nhưng không thay đổi tỷ lệ khung hình) trừ không gian dưới cùng mà tôi sử dụng cho div với một số văn bản, nút, v.v. w3c & css tất nhiên).

EDIT: Tôi đã tìm thấy lý do, thẻ video giống như văn bản, không phải là một thành phần khối, vì vậy tôi đã sửa nó bằng css này:

 video{
  display:block;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

Lưu ý display:block;thẻ trên video.


0

Tôi không chắc liệu điều này có hoạt động trong tình huống cụ thể của bạn không, nhưng tôi đã thấy rằng việc đệm vào div bên trong sẽ đẩy nội dung xung quanh bên trong div nếu div chứa có kích thước cố định. Bạn sẽ phải nổi hoặc hoàn toàn định vị phần tử tiêu đề của mình, nhưng nếu không, tôi đã không thử điều này cho các div có kích thước thay đổi.

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.