En boy oranı korunsun ancak CSS'de ekran genişliği ve yüksekliği doldurulsun mu?


122

16:9Video gibi yaklaşık yatay sabit en boy oranına sahip bir sitem var .

Mevcut genişliği ve mevcut yüksekliği doldurmak için ortalanmasını ve genişletilmesini istiyorum, ancak her iki tarafta da asla büyümemesini istiyorum.

Örneğin:

  1. Uzun ve ince bir sayfa, orantılı bir yüksekliği korurken tam genişliğe kadar uzanan içeriğe sahip olacaktır.
  2. Kısa geniş bir sayfa, orantılı bir genişlikle tam yüksekliğe uzanan içeriğe sahip olacaktır.

Baktığım iki yöntem var:

  1. Bir kapsayıcıyı genişletmek için doğru en boy oranına sahip bir görüntü kullanın div, ancak büyük tarayıcılarda aynı şekilde davranmasını sağlayamadım.
  2. Orantılı bir alt dolgu ayarlamak, ancak bu yalnızca genişliğe göre çalışır ve yüksekliği yok sayar. Genişlikle birlikte büyümeye devam ediyor ve dikey kaydırma çubuklarını gösteriyor.

Bunu JS ile kolayca yapabileceğinizi biliyorum, ancak saf bir CSS çözümü istiyorum.

Herhangi bir fikir?


sitepoint.com/... Seti kapsayıcı div içinposition: relative (default) height: 0 padding-<top/bottom>: H/W*100%
Ujjwal Singh

Yanıtlar:


280

Yeni CSS görüntü alanı birimlerini vw ve vh(görüntü alanı genişliği / görüntü alanı yüksekliği) kullanın

VAKTİNİ BOŞA HARCAMAK

Dikey ve yatay olarak yeniden boyutlandırdığınızda, öğenin her zaman maksimum görüntü alanı boyutunu oranı bozmadan ve kaydırma çubukları olmadan dolduracağını göreceksiniz!

(SAF) CSS

div
{
    width: 100vw; 
    height: 56.25vw; /* height:width ratio = 9/16 = .5625  */
    background: pink;
    max-height: 100vh;
    max-width: 177.78vh; /* 16/9 = 1.778 */
    margin: auto;
    position: absolute;
    top:0;bottom:0; /* vertical center */
    left:0;right:0; /* horizontal center */
}

Görünüm alanının maksimum% 90 genişliğini ve yüksekliğini kullanmak istiyorsanız: FIDDLE

Ayrıca, tarayıcı desteği de oldukça iyidir: IE9 +, FF, Chrome, Safari- caniuse


1
Bu gerçekten güzel ve temiz bir çözüm. Biraz daha geriye dönük tarayıcı desteği ile ideal olarak yapabilirim. Sanırım daha eski bir tarayıcıda minimum bir genişliğe / yüksekliğe sahip olursunuz ve bunu buna ayarlarsınız - eğer kaydırma çubukları olsaydı
Henry Gibson

8
Uhm .. 2 günlük çalışma ve sonsuz sayıda kullanıcı hüsranından kurtardığın için teşekkürler. 1000'den fazla yapabilirsem.
Schoening

2
Bana çok zaman kazandırdın. Çok teşekkür ederim.
Dylan Gattey

1
Ne yazık ki, son iOS sürümleri desteklemez veya viewport birimlerinin kırık uygulanmasını var ( vh, vw, vmin, vmax). Ancak, iOS cihazlarını hedeflemek için medya sorgularını kullanan bir geçici çözüm var .
Tim

1
seni seviyorum. harika çözüm!
Guttemberg

20

Daha Danieldfazla kullanım için yanıtını DAHA AZ bir karışımda yeniden formüle etmek :

// Mixin for ratio dimensions    
.viewportRatio(@x, @y) {
  width: 100vw;
  height: @y * 100vw / @x;
  max-width: @x / @y * 100vh;
  max-height: 100vh;
}

div {

  // Force a ratio of 5:1 for all <div>
  .viewportRatio(5, 1);

  background-color: blue;
  margin: 0;
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
}

11

CSS görüntü alanı birimleriyle birlikte bir CSS medya sorgusu kullanın ve görüntü alanının en boy oranına uyarlayın. Bu, diğer özellikleri de güncelleme avantajına sahiptir .@media vwvhfont-size

Bu keman , div için sabit en boy oranını ve ölçeğiyle tam olarak eşleşen metni gösterir.

İlk boyut, tam genişliğe bağlıdır:

div {
  width: 100vw; 
  height: calc(100vw * 9 / 16);

  font-size: 10vw;

  /* align center */
  margin: auto;
  position: absolute;
  top: 0px; right: 0px; bottom: 0px; left: 0px;

  /* visual indicators */
  background:
    url(data:image/gif;base64,R0lGODlhAgAUAIABAB1ziv///yH5BAEAAAEALAAAAAACABQAAAIHhI+pa+EPCwA7) repeat-y center top,
    url(data:image/gif;base64,R0lGODlhFAACAIABAIodZP///yH5BAEAAAEALAAAAAAUAAIAAAIIhI8Zu+nIVgEAOw==) repeat-x left center,
    silver;
}

Ardından, görüntü alanı istenen en boy oranından daha geniş olduğunda, temel ölçü olarak yüksekliğe geçin:

/* 100 * 16/9 = 177.778 */
@media (min-width: 177.778vh) {
  div {
    height: 100vh;
    width: calc(100vh * 16 / 9);

    font-size: calc(10vh * 16 / 9);
  }
}

Bu, @Danield'ın yaklaşımınamax-width ve max-height yaklaşımına çok benzer , sadece daha esnektir.


7

Bununla ilgili asıl sorum, her ikisinin de sabit bir yönü olan bir öğeye nasıl sahip olacağıydı, ancak bunu belirli bir kaba tam olarak sığdırmak, bu da onu biraz karmaşık hale getiriyor. Tek bir öğenin en boy oranını korumasını istiyorsanız, çok daha kolaydır.

Karşılaştığım en iyi yöntem, bir elemana sıfır yükseklik vermek ve sonra ona yükseklik vermek için yüzde dolgu-taban kullanmaktır. Yüzde dolgusu her zaman bir öğenin genişliğiyle orantılıdır ve üst veya alt dolgusu olsa bile yüksekliğiyle orantılı değildir.

W3C Dolgu Özellikleri

Böylece, bir öğeye bir kap içinde oturması için bir yüzde genişliği verebilirsiniz ve ardından en boy oranını veya başka bir deyişle genişliği ile yüksekliği arasındaki ilişkiyi belirtmek için dolgu yapabilirsiniz.

.object {
    width: 80%; /* whatever width here, can be fixed no of pixels etc. */
    height: 0px;
    padding-bottom: 56.25%;
}
.object .content {
    position: absolute;
    top: 0px;
    left: 0px;
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    -moz-box-sizing: border-box;
    padding: 40px;
}

Dolayısıyla, yukarıdaki örnekte nesne kap genişliğinin% 80'ini alır ve sonra yüksekliği bu değerin% 56,25'idir. Genişliği 160 piksel ise, alt dolgu ve dolayısıyla yükseklik 90 piksel, yani 16: 9 en boy oranı olacaktır.

Burada sizin için sorun olmayabilecek ufak bir sorun, yeni nesnenizin içinde doğal alan olmamasıdır. Örneğin bir metin girmeniz gerekiyorsa ve bu metnin kendi dolgu değerlerini alması gerekiyorsa, içine bir kap eklemeniz ve orada özellikleri belirtmeniz gerekir.

Ayrıca vw ve vh birimleri bazı eski tarayıcılarda desteklenmez, bu yüzden soruma kabul edilen cevap sizin için mümkün olmayabilir ve daha fazla lo-fi kullanmanız gerekebilir.


Fazladan işaretlemeyi kullanmaktan kaçınmak için, :: before veya :: after kullanarak bir öğe ekleyebilir ve bu öğeye nesnenin kendi genişliğine ve 0 genişliğine göre bir yükseklik 0 ve bir dolgu-alt verebilirsiniz. Bu aynı etkiye sahip olacak ancak daha az işaretleme ile tüm nesne alanını bir konteynere gerek kalmadan içeri koymak için kullanılabilir hale getirecektir.
Henry Gibson

6

Anladığım kadarıyla, CSSbelirli bir çözüm isteyeceğinizi sormuştunuz . En boy oranını korumak için yüksekliği istenen en boy oranına bölmeniz gerekir. 16: 9 = 1.777777777778.

Kap için doğru yüksekliği elde etmek için, mevcut genişliği 1.777777777778'e bölmeniz gerekir. widthKonteyneri sadece ile kontrol edemeyeceğiniz CSSveya bir yüzdeyle bölünemeyeceğiniz için CSS,JavaScript (bildiğim kadarıyla) .

İstenilen en boy oranını koruyacak bir çalışma senaryosu yazdım.

HTML

<div id="aspectRatio"></div>

CSS

body { width: 100%; height: 100%; padding: 0; margin: 0; }
#aspectRatio { background: #ff6a00; }

JavaScript

window.onload = function () {
    //Let's create a function that will scale an element with the desired ratio
    //Specify the element id, desired width, and height
    function keepAspectRatio(id, width, height) {
        var aspectRatioDiv = document.getElementById(id);
        aspectRatioDiv.style.width = window.innerWidth;
        aspectRatioDiv.style.height = (window.innerWidth / (width / height)) + "px";
    }

    //run the function when the window loads
    keepAspectRatio("aspectRatio", 16, 9);

    //run the function every time the window is resized
    window.onresize = function (event) {
        keepAspectRatio("aspectRatio", 16, 9);
    }
}

functionFarklı bir orana sahip başka bir şey görüntülemek isterseniz tekrar kullanabilirsiniz.

keepAspectRatio(id, width, height);

Cevabınız için teşekkürler. Bunu komut dosyasında yapmak nispeten basit, ancak gerçekten CSS tabanlı bir çözüm istedim. Gerçekten hızlı ve güvenilir bir yanıt veren çözüm istiyorum ve bazen farklı tarayıcılardaki olayları yeniden boyutlandırma biraz gecikmeli buluyorum. Dönüşümünüzü, tarayıcı yeniden boyutlandırıldıktan biraz sonra yaparsınız, bu nedenle en iyi kullanıcı deneyimini vermez. Tarayıcının boyut değiştirdiği anda ortaya çıkan bir şey, dolayısıyla saf CSS istersiniz.
Henry Gibson

1
@Henry Gibson Komut dosyası Chrome, FF, IE, Opera ve Safari'de test edilmiştir. Tümü hızlı çalışır ve tarayıcıların eski sürümlerinde bile güvenilirdir. Her tarayıcı kendi olaylarını ateşler. window.onresizetarayıcının boyutu değiştiği anda tetiklenir.
MCSharp

son kullanıcıların tarayıcıları neredeyse geliştiriciler kadar yeniden boyutlandırmadığını unutmayın
Simon_Weaver


1

Danield'in cevabı iyidir, ancak yalnızca div tüm görüntü alanını doldurduğunda veya birazcalc alanındaki diğer içeriğin genişliği ve yüksekliği biliniyorsa, bir miktar kullanılabilir.

Bununla birlikte, margin-bottomhile yukarıda belirtilen cevaptaki yöntemle birleştirilerek, sorun sadece diğer içeriğin yüksekliğini bilmek zorunda kalmaya indirgenebilir. Bu, sabit bir yükseklik başlığınız varsa kullanışlıdır, ancak örneğin kenar çubuğunun genişliği bilinmiyor.

body {
  margin: 0;
  margin-top: 100px; /* simulating a header */
}

main {
  margin: 0 auto;
  max-width: calc(200vh - 200px);
}

section {
  padding-bottom: 50%;
  position: relative;
}

div {
  position:absolute;
  background-color: red;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}
<main>
  <section>
    <div></div>
  </section>
</main>

Burada scss kullanan bir jsfiddle'da , bu da değerlerin nereden geldiğini daha açık hale getiriyor.


0

Daniel'in cevabına dayanarak, #{}Bootstrap kalıcı iletişim kutusundaki bir youtube videosunun iframe'i için bu SASS karışımını interpolasyonla ( ) yazdım :

@mixin responsive-modal-wiframe($height: 9, $width: 16.5,
                                $max-w-allowed: 90, $max-h-allowed: 60) {
  $sides-adjustment: 1.7;

  iframe {
    width: #{$width / $height * ($max-h-allowed - $sides-adjustment)}vh;
    height: #{$height / $width * $max-w-allowed}vw;
    max-width: #{$max-w-allowed - $sides-adjustment}vw;
    max-height: #{$max-h-allowed}vh;
  }

  @media only screen and (max-height: 480px) {
    margin-top: 5px;
    .modal-header {
      padding: 5px;
      .modal-title {font-size: 16px}
    }
    .modal-footer {display: none}
  }
}

Kullanımı:

.modal-dialog {
  width: 95vw; // the modal should occupy most of the screen's available space
  text-align: center; // this will center the titles and the iframe

  @include responsive-modal-wiframe();
}

HTML:

<div class="modal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title">Video</h4>
      </div>
      <div class="modal-body">
        <iframe src="https://www.youtube-nocookie.com/embed/<?= $video_id ?>?rel=0" frameborder="0"
          allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
          allowfullscreen></iframe>
      </div>
      <div class="modal-footer">
        <button class="btn btn-danger waves-effect waves-light"
          data-dismiss="modal" type="button">Close</button>
      </div>
    </div>
  </div>
</div>

Bu, videoyu her zaman, genişlik veya yükseklik videoyla orantılı olmadığında youtube'un iframe'e eklediği siyah kısımlar olmadan görüntüler. Notlar:

  • $sides-adjustment yanlarda görünen bu siyah parçaların küçük bir bölümünü telafi etmek için hafif bir ayardır;
  • çok düşük yükseklikteki cihazlarda (<480px) standart mod çok fazla yer kaplıyor, bu yüzden şunu yapmaya karar verdim:
    1. gizle .modal-footer;
    2. konumunu ayarlayın .modal-dialog;
    3. boyutlarını küçültün .modal-header.

Bir çok testten sonra, bu artık benim için kusursuz çalışıyor.


-1

burada bir div içinde bile çalışan @Danield çözümüne dayalı bir çözüm.

Bu örnekte, Angular kullanıyorum ancak hızlı bir şekilde vanilla JS veya başka bir çerçeveye geçebilir.

Ana fikir, @Danield çözümünü boş bir iframe içinde taşımak ve iframe pencere boyutu değiştikten sonra boyutları kopyalamaktır.

İframe'in, baba öğesiyle boyutlara uyması gerekir.

https://stackblitz.com/edit/angular-aspect-ratio-by-iframe?file=src%2Findex.html

İşte birkaç ekran görüntüsü:

görüntü açıklamasını buraya girin

görüntü açıklamasını buraya girin

görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.