Truy vấn phương tiện có thể thay đổi kích thước dựa trên một yếu tố div thay vì màn hình?


317

Tôi muốn sử dụng truy vấn phương tiện để thay đổi kích thước các phần tử dựa trên kích thước của divphần tử mà chúng đang ở. Tôi không thể sử dụng kích thước màn hình vì divnó chỉ được sử dụng như một tiện ích trong trang web và kích thước của nó có thể thay đổi.

Cập nhật

Có vẻ như có công việc đang được thực hiện ngay bây giờ: https://github.com/ResponsiveImagesCG/cq-demos


2
Tôi nghĩ rằng câu hỏi này quá ngắn gọn để có được một câu trả lời tốt. Có lẽ bạn có thể cung cấp một ví dụ về những gì bạn đang cố gắng làm? Có thể sử dụng jsfiddle.net để kiểm tra ý tưởng của bạn và cho phép người khác giúp bạn? Nói chung, không có lý do cho những gì bạn đang hỏi, bạn sẽ có thể đạt được kết quả mong muốn với CSS mà không cần truy vấn phương tiện. Bạn có thể sử dụng kích thước phần trăm và ems cho phông chữ để chia tỷ lệ các phần tử lồng nhau. Nhưng có lẽ tôi chỉ cần xem một ví dụ về mã html và css của bạn để hiểu rõ hơn?
BenSwayne

1
Làm thế nào có thể kích thước của widget của bạn khác nhau? Là trang của bạn có chiều rộng cố định (ví dụ 960px) với chế độ xem trên 1024px hoặc cả hai đều trôi chảy? Điều đó không rõ ràng và sẽ hữu ích để biết
FelipeAls

3
Trên thực tế, dự án hiện tại của tôi có một tình huống tương tự. Một danh sách các mục được hiển thị theo bố cục 2 col cho các thiết bị rộng hoặc bố trí 1 col cho các thiết bị hẹp, nhưng một mục duy nhất sẽ ở trong bố cục 1 col cho dù thế nào đi chăng nữa. Cả danh sách và phiên bản đơn đều có 2 yếu tố khá rộng và ngắn. Trên các thiết bị rộng hơn, 2 yếu tố trông cạnh nhau tốt nhất. Lý tưởng nhất là các thiết bị hẹp: luôn luôn thẳng đứng, thiết bị rộng: luôn song song, ở đâu đó giữa (phụ thuộc 1 hoặc 2-col): dọc hoặc song song. Nổi là giải pháp đơn giản, nhưng chiều rộng cũng cần thay đổi tùy theo bố cục.
cimmanon

1
LESS sẽ được biên dịch thành CSS, vì vậy nếu CSS không hỗ trợ, LESS cũng không thể giúp bạn.
jvannistelrooy

3
Liên kết không còn hoạt động?
mix3d

Câu trả lời:


228

Không, truy vấn phương tiện không được thiết kế để hoạt động dựa trên các yếu tố trong một trang. Chúng được thiết kế để hoạt động dựa trên các thiết bị hoặc loại phương tiện (do đó tại sao chúng được gọi là truy vấn phương tiện ). width, heightvà các tính năng đa phương tiện dựa trên kích thước khác đều đề cập đến kích thước của chế độ xem hoặc màn hình của thiết bị trong phương tiện dựa trên màn hình. Chúng không thể được sử dụng để chỉ một yếu tố nhất định trên một trang.

Nếu bạn cần áp dụng các kiểu tùy thuộc vào kích thước của một divyếu tố nhất định trên trang của mình, bạn sẽ phải sử dụng JavaScript để quan sát các thay đổi về kích thước của divyếu tố đó thay vì truy vấn phương tiện.


Tôi đã nghe về một số cách tôi có thể sử dụng các hàm với các truy vấn phương tiện để lấy kích thước từ một phần tử có chứa. Có một số cách tôi có thể kết hợp điều này với các truy vấn phương tiện để thay đổi kích thước các yếu tố?
Yazz.com

1
Bạn sẽ phải sử dụng JS để định kỳ lấy chiều rộng của phần tử của mình và phản ứng tương ứng (định kỳ = mỗi giây hoặc lâu hơn hoặc nó sẽ làm chậm một số trình duyệt; theo đó = bằng cách bật các lớp tạo kiểu cho widget của bạn nếu bạn muốn phương thức nhanh nhất).
FelipeAls

6
Để thực hiện điều này nguyên bản, chúng ta cần @elementtruy vấn. W3C có một số tài liệu tốt về vần điệu / lý do cho @mediacác truy vấn: w3.org/TR/css3-mediaqueries/# thong (liên kết này sẽ đưa bạn đến phần thảo luận về độ rộng --- độ rộng của loại phương tiện, không phải là các yếu tố có trong)
Dawson

Bất kỳ cơ hội để làm cho nó hoạt động trong email? Tôi đang cố gắng áp dụng kiểu dáng di động cho email khi div container quá nhỏ (ví dụ: khi không gian email của phiên bản máy tính để bàn quá nhỏ để phù hợp với thiết kế 2 cột, chẳng hạn do thay đổi kích thước cửa sổ).
Lev

Nhân tiện, các truy vấn @element sẽ biến css thành ngôn ngữ hoàn chỉnh Turing
Nick

117

Tôi vừa tạo một shim javascript để đạt được mục tiêu này. Hãy xem nếu bạn muốn, đó là một bằng chứng về khái niệm, nhưng hãy cẩn thận: đó là phiên bản đầu tiên và vẫn cần một số công việc.

https://github.com/marcj/css-element-queries


5
Cảm ơn, tôi rất ấn tượng
Yazz.com

5
Điều này thật phi thường. Kết hợp với bootstrap đáp ứng Tôi đang làm một số thứ tuyệt vời không thể đạt được chỉ với @media. Làm tốt.
Aku

3
Bạn đã cứu mạng chúng tôi
Broda Noel

Wow, thực sự tốt đẹp, làm cho mọi thứ dễ dàng hơn nhiều
kaiser

Mát mẻ. Có câu hỏi. Làm thế nào để phát hiện plugin này - những yếu tố cần min-widthgia hạn thuộc tính; Tôi có cần phải viết thủ công danh sách lớp css, các yếu tố được đánh dấu, được bật để min-widthgia hạn không?
Alexander Goncharov

38

Truy vấn phương tiện bên trong iframe có thể hoạt động như một truy vấn phần tử. Tôi đã thực hiện thành công điều này. Ý tưởng xuất phát từ một bài đăng gần đây về Quảng cáo đáp ứng của Zurb. Không có Javascript!


Tôi nghĩ rằng đây là giải pháp tốt nhất, bởi vì, các truy vấn phương tiện hoạt động trong iframe.
emfi

25

Điều này hiện không thể thực hiện được với CSS vì @BoltClock đã viết trong câu trả lời được chấp nhận, nhưng bạn có thể giải quyết vấn đề đó bằng cách sử dụng JavaScript.

Tôi đã tạo một truy vấn container (còn gọi là truy vấn phần tử) prolyfill để giải quyết loại vấn đề này. Nó hoạt động hơi khác so với các tập lệnh khác, vì vậy bạn không phải chỉnh sửa mã HTML của các thành phần. Tất cả bạn phải làm là bao gồm tập lệnh và sử dụng nó trong CSS của bạn như vậy:

.element:container(width > 99px) {
    /* If its container is at least 100px wide */
}

https://github.com/ausi/cq-prolyfill


2
Nó chứa đầy JS. Mục tiêu là chỉ có chức năng trong CSS.
Màu xanh lá cây

13
Prolyfills (và polyfill ) thường được viết bằng JS để cho phép một tính năng chưa được trình duyệt hỗ trợ. Mục tiêu của prolyfill là trở nên lỗi thời một khi tính năng này được hỗ trợ trong CSS.
ausi

3
@ius không có đề cập đến CSS CSS chỉ có trong câu hỏi. Làm thế nào bạn đi đến kết luận đó?
ausi

1
@ius ngoại trừ bạn không thể làm điều đó trong CSS, vì vậy việc đưa ra một giải pháp bên ngoài css là hoàn toàn hợp lý. Tốt hơn nhiều so với "không bạn không thể" bạn không nghĩ vậy;)
Wesley Smith

1
@ DelightedD0D sau bình luận của tôi, anh ấy đã thay đổi câu trả lời và tôi đã bình chọn +1 cho thay đổi. Câu trả lời hiện tại là ổn đối với tôi vì nói rằng điều này là không thể với CSS.
ius

17

Tôi đã gặp vấn đề tương tự một vài năm trước đây và tài trợ cho việc phát triển một plugin để giúp tôi trong công việc. Tôi đã phát hành plugin dưới dạng mã nguồn mở để những người khác cũng có thể hưởng lợi từ nó và bạn có thể lấy nó trên Github: https://github.com/eqcss/eqcss

Có một số cách chúng ta có thể áp dụng các kiểu phản hồi khác nhau dựa trên những gì chúng ta có thể biết về một yếu tố trên trang. Dưới đây là một vài truy vấn phần tử mà plugin EQCSS sẽ cho phép bạn viết bằng CSS:

@element 'div' and (condition) {
  $this {
    /* Do something to the 'div' that meets the condition */
  }
  .other {
    /* Also apply this CSS to .other when 'div' meets this condition */
  }
}

Vì vậy, những điều kiện được hỗ trợ cho các kiểu đáp ứng với EQCSS?

Truy vấn trọng lượng

  • chiều rộng tối thiểu trong px
  • chiều rộng tối thiểu trong %
  • chiều rộng tối đa trong px
  • chiều rộng tối đa trong %

Truy vấn chiều cao

  • chiều cao tối thiểu trong px
  • chiều cao tối thiểu trong %
  • chiều cao tối đa trong px
  • chiều cao tối đa trong %

Truy vấn số

  • ký tự tối thiểu
  • ký tự tối đa
  • dòng tối thiểu
  • dòng tối đa
  • trẻ em
  • trẻ em tối đa

Bộ chọn đặc biệt

Bên trong các truy vấn phần tử EQCSS, bạn cũng có thể sử dụng ba bộ chọn đặc biệt cho phép bạn áp dụng cụ thể hơn các kiểu của mình:

  • $this (phần tử phù hợp với truy vấn)
  • $parent (phần tử cha của (các) phần tử phù hợp với truy vấn)
  • $root(yếu tố gốc của tài liệu, <html>)

Các truy vấn phần tử cho phép bạn soạn bố cục của mình ra khỏi các mô-đun thiết kế đáp ứng riêng lẻ, mỗi mô-đun có một chút 'tự nhận thức' về cách chúng được hiển thị trên trang.

Với EQCSS, bạn có thể thiết kế một tiện ích để trông đẹp từ rộng 150px cho đến rộng 1000px, sau đó bạn có thể tự tin thả tiện ích đó vào bất kỳ thanh bên nào trong bất kỳ trang nào bằng bất kỳ mẫu nào (trên bất kỳ trang web nào) và


1
Dự án tốt đẹp! Tôi đã xem những gì bạn đã thực hiện
Yazz.com

@innovati Tôi tìm thấy bài đăng này trong khi tìm cách để thực hiện truy vấn trên các yếu tố. Tôi dường như không thể làm cho nó hoạt động. Bạn có phiền khi nhìn vào vé của tôi không? github.com/eqcss/eqcss/issues/96
Andrew Newby

10

Từ góc độ bố trí, có thể sử dụng các kỹ thuật hiện đại.

Nó được tạo thành (tôi tin) bởi Heydon Pickering. Ông chi tiết quá trình tại đây: http://www.heydonworks.com/article/the-flexbox-holy-albatross

Chris Coyier chọn nó và làm việc thông qua bản demo của nó tại đây: https://css-tricks.com/pocking-the-flexbox-albatross-to-real-use/

Để xác định lại vấn đề này, dưới đây chúng ta thấy 3 của cùng một thành phần, mỗi tạo thành từ ba divs cam dán nhãn a, bc.

Các khối thứ hai của hai hiển thị theo chiều dọc, bởi vì chúng bị giới hạn trong phòng nằm ngang, trong khi các khối 3 thành phần trên cùng được đặt theo chiều ngang.

Nó sử dụng thuộc tính flex-basisCSS và các biến CSS để tạo hiệu ứng này.

Ví dụ cuối cùng

.panel{
  display: flex;
  flex-wrap: wrap;
  border: 1px solid #f00;
  $breakpoint: 600px;
  --multiplier: calc( #{$breakpoint} - 100%);
  .element{
    min-width: 33%;
    max-width: 100%;
    flex-grow: 1;
    flex-basis: calc( var(--multiplier) * 999 );
  }
}

Bản giới thiệu

Bài viết của Heydon là 1000 từ giải thích chi tiết và tôi khuyên bạn nên đọc nó.


Điều đó từ bài viết của Heydon ... Trông và hoạt động như ma thuật! Cảm ơn bạn đã phản hồi của bạn, là tuyệt vời.
ptyskju

2
Đây là câu trả lời mà tất cả mọi người vấp phải câu hỏi này đang tìm kiếm
TehShrike

7

Câu hỏi rất mơ hồ. Như BoltClock nói, các truy vấn phương tiện chỉ biết kích thước của thiết bị. Tuy nhiên, bạn có thể sử dụng truy vấn phương tiện kết hợp với bộ chọn giảm dần để thực hiện điều chỉnh.

.wide_container { width: 50em }

.narrow_container { width: 20em }

.my_element { border: 1px solid }

@media (max-width: 30em) {
    .wide_container .my_element {
        color: blue;
    }

    .narrow_container .my_element {
        color: red;
    }
}

@media (max-width: 50em) {
    .wide_container .my_element {
        color: orange;
    }

    .narrow_container .my_element {
        color: green;
    }
}

Giải pháp duy nhất khác yêu cầu JS.


47
Câu hỏi không mơ hồ chút nào. Trong thực tế, nó là một câu hỏi rất tốt. Thật không may, không có câu trả lời tốt cho nó.
stepanian

2
Bảo trì khủng khiếp bằng cách sử dụng phương pháp này.
Totty.js

4

Cách duy nhất tôi có thể nghĩ rằng bạn có thể hoàn thành những gì bạn muốn hoàn toàn với css, là sử dụng một thùng chứa chất lỏng cho vật dụng của bạn. Nếu chiều rộng của bộ chứa của bạn là một tỷ lệ phần trăm của màn hình thì bạn có thể sử dụng các truy vấn phương tiện để định kiểu tùy thuộc vào chiều rộng của bộ chứa của bạn, vì bây giờ bạn sẽ biết cho mỗi kích thước của màn hình, kích thước của bộ chứa của bạn là gì. Ví dụ: giả sử bạn quyết định tạo cho 50% chiều rộng màn hình của bộ chứa. Sau đó, đối với chiều rộng màn hình 1200px, bạn biết rằng thùng chứa của bạn là 600px

.myContainer {
  width: 50%;
}

/* you know know that your container is 600px 
 * so you style accordingly
*/
@media (max-width: 1200px) { 
  /* your css for 600px container */
}

Không, nó trông xấu xí trên màn hình. Kích thước màn hình thay đổi nhanh hơn, nhưng phần tử xuất hiện trên màn hình sau và nhỏ hơn.
Màu xanh lá cây

3

Tôi cũng đã nghĩ đến các truy vấn truyền thông, nhưng sau đó tôi đã tìm thấy điều này:

Chỉ cần tạo một trình bao bọc <div>với giá trị phần trăm cho padding-bottom, như thế này:

div {
  width: 100%;
  padding-bottom: 75%;
  background:gold; /** <-- For the demo **/
}
<div></div>

Nó sẽ dẫn đến một <div> chiều cao bằng 75% chiều rộng của thùng chứa của nó (tỷ lệ khung hình 4: 3).

Kỹ thuật này cũng có thể được kết hợp với các truy vấn phương tiện và một chút kiến ​​thức đặc biệt về bố cục trang để kiểm soát chi tiết hơn.

Nó đủ cho nhu cầu của tôi. Mà có thể là đủ cho nhu cầu của bạn quá.


2

Bạn có thể sử dụng ResizeObserver API . Vẫn còn trong những ngày đầu nên nó chưa được tất cả các trình duyệt hỗ trợ (nhưng có một số polyfill có thể giúp bạn điều đó).

Về cơ bản API này cho phép bạn đính kèm một trình lắng nghe sự kiện để thay đổi kích thước của một phần tử DOM.

Bản demo 1 - Bản demo 2


Có một polyfill cho đặc tả dự thảo. github.com/jugg/resize-observer
Trevor Karjanis

Bài viết của Heydon cung cấp một ví dụ thực hiện điều này. Tìm kiếm "ResizeObserver" trên trang: heydonworks.com/article/the-flexbox-holy-albatross
Gabe Rogan

0

Đối với tôi, tôi đã làm điều đó bằng cách đặt chiều rộng tối đa của div, do đó, đối với tiện ích nhỏ sẽ không bị ảnh hưởng và tiện ích lớn bị thay đổi kích thước do kiểu chiều rộng tối đa.

  // assuming your widget class is "widget"
  .widget {
    max-width: 100%;
    height: auto;
  }

Câu hỏi đề cập rằng kích thước widget có thể thay đổi, đặt chiều rộng tối đa sẽ không thay đổi kích thước của widget khi container rộng. .widgetchỉ là một mẫu làm lớp cho div của widget.
Jacky Choo
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.