Подтвердить что ты не робот

CSS background-size: cover + background-attachment: фиксированные обрезки фоновых изображений

У меня есть список цифр, содержащих фоновые изображения. Что-то вроде следующего:

<ul>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
  <li>
    <figure style="background-image: url(...);"></figure>
  </li>
</ul>

Каждое из этих изображений имеет background-size для cover и background-attachment для fixed.

figure {
  width: 100%;
  height: 100%;
  background-size: cover;
  background-attachment: fixed;
}

Когда каждая фигура занимает весь видовой экран, это работает отлично, но если есть смещение любого типа, фоновое изображение обрезается.

Насколько я могу судить по дизайну (https://developer.mozilla.org/en-US/docs/Web/CSS/background-size#Values).

Я хотел бы, чтобы изображения либо были скопированы по вертикали или по горизонтали, но не по обеим сторонам и центрированы по размеру самой фигуры.

Я знаю, что есть javascript-решения, но есть ли способ сделать это с помощью CSS?

Вот рабочий пример: http://codepen.io/Godwin/pen/KepiJ

4b9b3361

Ответ 1

К сожалению, это просто артефакт о том, как фиксированное позиционирование работает в CSS, и нет никакого способа обойти его в чистом CSS - вы должны использовать Javascript.

Причина этого происходит из-за комбинации background-attachment: fixed и background-size: cover. Когда вы указываете background-attachment: fixed, это по существу приводит к тому, что background-image ведет себя так, как если бы это было изображение position: fixed, что означало, что оно выведено из контекста потока и позиционирования страницы и становится относительно видового экрана, а не элементом, которым он является фон изображение.

Поэтому всякий раз, когда вы используете эти свойства вместе, значение cover вычисляется относительно размера окна просмотра независимо от размера самого элемента, поэтому он работает так, как ожидалось, когда элемент имеет тот же размер, что и в окне просмотра, но обрезается неожиданными способами, когда элемент меньше, чем область просмотра.

Чтобы обойти это, вам в основном нужно использовать background-attachment: scroll и привязать прослушиватель событий к событию scroll в JS, который вручную обновляет background-position относительно того, как далеко прокручивалось окно, чтобы имитировать фиксированное позиционирование но все равно вычисляет background-size: cover относительно элемента контейнера, а не области просмотра.

Ответ 2

Здесь исправлено jQuery: http://jsfiddle.net/QN9cH/1/ Я знаю, что это не оптимально, но, по крайней мере, это работает:)

$(window).scroll(function() {
  var scrolledY = $(window).scrollTop();
  $('#container').css('background-position', 'left ' + ((scrolledY)) + 'px');
});

Ответ 3

Размер фона: обложка; свойство действительно обрезает изображение, чтобы оно могло заполнить область и не иметь пустого пространства.

Размер фона: содержать; свойство определяет, какое измерение больше и масштабируется в соответствии с этим. Поэтому, если у вас есть блок 100px x 100px и фоновое изображение размером 200x150px, установка размера фона будет масштабировать изображение до 100x75px. Однако в этом сценарии у вас будет пустое пространство, если соотношение сторон элемента отличается от изображения.

Вы также можете вручную управлять тем, какая доля имеет приоритет, при условии, что вы знаете соотношение сторон изображения.

Итак, если вы знаете, что ваше изображение всегда 100x200px, это означает, что ширина всегда является малым размером и высотой большой.

Теперь установите размер фона: 100% авто; будет гарантировать, что вы не получите пустое пространство, но в итоге вы получите отсечение. Если вы установите его в размере фона: авто 100%; он гарантирует, что не будет никакого отсечения, и высота никогда не будет иметь пустое пространство (но ширина будет).

Если вы хотите обрезать и просто центрировать изображение, используйте background-position: 50%;.

Ответ 4

Ответ Ника Noordijk поставил меня на правильный путь, но мне нравится избегать сценариев, которые выполняют вычисления каждый раз, когда происходит событие прокрутки. Здесь моя версия, которая выполняет только расчет при загрузке страниц или изменении размера экрана:

HTML:

<div class="fake-img"></div>

CSS

.fake-img {
    display: block;
    height: 280px;  /* set the height here */
    width: 100%;
    background-image: url('http://example.com/path/to/image.jpg');
    background-repeat: no-repeat;
    background-position: center 68px;
    background-size: auto 50%; /* make a "best guess" here as a default */
    background-attachment: fixed;
    position: relative;
}

JQuery

$(window).on('resize load orientationchange', function(){
    responsive_calc();
});

var responsive_calc = function(){

    // get the viewport height
    var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

    // get the element height
    var bannerHeight = $('.fake-img').height();

    // get the integer percentage value difference between them
    var bgHeightPercent = Math.ceil(bannerHeight/h*100);

    // set background-size height to match the element instead of the viewport
    $('.fake-img').css('background-size', 'auto ' + bgHeightPercent + '%');
}

Обратите внимание, что это действительно работает только с пейзажными "баннерными" изображениями - использование background-size: auto nn% не имеет того же преимущества background-size: cover при работе независимо от того, имеет ли ваше изображение избыток в любом направлении.

Ответ 5

background: url(<image>) center top no-repeat fixed;
background-size: auto <width size in %>;

Реального решения нет. Однако вы можете сделать размер высоты изображения auto вместо cover. И отрегулируйте размер ширины в% в элементе, пока он не укусит границу.

Вы видите, измените ли вы свое окно, оно не будет обрезано. Вместо этого он всегда будет поддерживать формат исходного изображения. При этом вы в основном "увеличиваете" его, но не "закрываете" его.

Ответ 6

Я сделал версию с отзывчивым фоновым изображением.

.flexslider .slides > li {
  background-position: center center;
  background-repeat: no-repeat;
  -webkit-background-size: cover;
  -moz-background-size: cover;
  -o-background-size: cover;
  background-size: cover;
}
#slider,
.alink {
  min-height: 300px
}
.alink {
  display: block
}

http://jsfiddle.net/onigetoc/grpku1gk/