背景画像を含む図のリストがあります。次のようなもの:
<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
残念ながら、これは単にCSSで固定位置がどのように機能するかの成果物であり、純粋なCSSでは回避できません。Javascriptを使用する必要があります。
これが発生する理由は、background-attachment: fixed
とbackground-size: cover
の組み合わせによるものです。 background-attachment: fixed
を指定すると、本質的にbackground-image
がposition: fixed
画像であるかのように動作します。つまり、ページフローと位置付けコンテキストから取り出され、背景画像である要素ではなくビューポートに対して相対的になります。
したがって、これらのプロパティを一緒に使用すると、エレメント自体のサイズに関係なく、ビューポートのサイズに対してcover
値が計算されます。これが、エレメントがビューポートが、要素がビューポートより小さい場合、予期しない方法で切り取られます。
これを回避するには、基本的にbackground-attachment: scroll
を使用し、イベントリスナをJSのscroll
イベントにバインドして、固定位置をシミュレートするためにウィンドウがスクロールされた距離に対してbackground-position
を手動で更新し、なおかつbackground-size: cover
を計算する必要がありますビューポートではなくコンテナ要素に関連します。
これにはjQueryの修正があります: http://jsfiddle.net/QN9cH/1/ 私はそれが最適ではないことを知っていますが、少なくともそれは動作します:)
$(window).scroll(function() {
var scrolledY = $(window).scrollTop();
$('#container').css('background-position', 'left ' + ((scrolledY)) + 'px');
});
background: url(<image>) center top no-repeat fixed;
background-size: auto <width size in %>;
実際の解決策はありません。ただし、auto
の代わりに画像のサイズをcover
にすることができます。そして、境界線に食い込むまで要素の幅サイズを%で調整します。
ウィンドウのサイズを変更すると、クリップされなくなります。代わりに、常に元の画像サイズ形式を維持します。上記を使用して、基本的に「ズーム」しますが、「カバー」しません。
背景サイズ:カバー;プロパティは実際に画像を切り取って、領域を埋め、空のスペースがないようにします。
Background-size:含む;プロパティは、どの次元が大きいかを決定し、それに応じてスケーリングします。したがって、100px x 100pxブロックと200x150pxの背景画像がある場合、背景サイズを含むように設定すると、画像は100x75pxにスケーリングされます。ただし、このシナリオでは、要素のアスペクト比が画像のアスペクト比と異なる場合、空のスペースがあります。
また、画像の縦横比がわかっている場合は、どの比率を優先するかを手動で制御することもできます。
したがって、画像が常に100x200pxであることがわかっている場合、これは幅が常に小さい寸法であり、高さが大きい寸法であることを意味します。
背景サイズの設定:100%auto;空のスペースを取得しないようにしますが、クリッピングが発生します。 background-sizeに設定した場合:auto 100%;クリッピングが発生せず、高さに空スペースが含まれないようにします(ただし、幅は空になります)。
クリッピングを行い、画像を中央に配置する場合は、background-position:50%;を使用します。
Nick 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
と同じ利点はありません。
個別に配置された要素の視差効果の例(フルスクリーン要素ではありません):
html:
<div style="background-image: url('/path/to/image.jpg')">Content</div>
css:
#element_to_scroll {
background-repeat: no-repeat;
background-size: cover;
background-position-x: center;
background-position-y: 0;
}
js:
$(window).scroll(function() {
var realImageWidth = 1280;
var realImageHeight = 1024;
var viewportBottom = $(window).scrollTop() + $(window).height();
$('#element_to_scroll').each(function(){
var scrollAmountPx = realImageHeight/(realImageWidth/$(this).outerWidth())-$(this).outerHeight();
var elementOffsetFromBottom = viewportBottom-$(this).offset().top;
var scrollAreaHeight = $(this).outerHeight() + $(window).height();
if(elementOffsetFromBottom>0 && elementOffsetFromBottom<scrollAreaHeight) {
var backgroundPositionOffset = Math.ceil(scrollAmountPx/scrollAreaHeight*elementOffsetFromBottom);
//$(this).css('background-position-y',"-"+backgroundPositionOffset+"px");
$(this).clearQueue().animate({'background-position-y':"-"+backgroundPositionOffset+"px"},50);
}
});
});
この記事 を読むまでこの同じ問題を抱えていたので、CSSにこの行を追加して機能させることができると教えてくれました。
will-change: transform;
動いた!
CSSは次のようになります。
.myClass{
position: relative;
background: hsla(300, 100%, 90%, 0.1);
overflow: hidden;
&::before {
background-image: url(/img/bg.jpg);
background-size: cover;
background-size: cover !important;
-webkit-background-size: cover !important;
background-repeat: repeat repeat !important;
background-attachment: scroll !important;//"fixed" is the desired effect, but mobile browsers find it too "expensive" and disabled it, so use "scroll"
background-position: 30% 50%;
@media(min-width: $screen-sm-min){
background-attachment: fixed !important;
background-position: 30% 20%;
will-change: transform;
}//768
content: "";
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.1;
}
}
Windows Chrome、Edge、Safariで動作します。しかし、Firefoxではありません。
別の非常に簡単な解決策は、vw
ユニットとvh
ユニットを使用することです(知らない場合、ほとんどの場合、 完全に問題のないブラウザーサポート があります) 。たとえば、background-size: cover
、 行う background-size: auto 100vh
。
vw
とvh
に慣れていない場合、これらはビューポートの単位であり、ビューポートの幅とビューポートの高さに対応しています。値は、ビューポートの高さまたは幅の割合に対応します。例えば、 50vw
は、ビューポート幅の50%を意味します。
この目的のために、背景をビューポートの高さの100%に単純に伝えることができます。
異なるアスペクト比に対応する必要がある場合は、 aspect-ratio @media rules を利用できます。