How to make background-image non-stretchable? - css

In my project I've set background image with the following attributes:
body {
background-image: url("/");
background-size: cover;
background-repeat: no-repeat;
}
But when there are lots of elements on some page, this image stretching and enlarging to the bottom and, therefore, becomes ugly. How to do it non-stretchable? So that I can scroll down and that image would be constant.
Here's the example of the image stretching on CodePen. Below is the snippet:
body {
background-image: url("http://www.planwallpaper.com/static/images/canberra_hero_image.jpg");
background-size: cover;
background-repeat: no-repeat;
}
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
<div class=col-md-4>
<div class="jumbotron">
Some element
</div>
</div>
</div>
</div>

If you do not want the background image to stretch then you should not set background-size: cover on the element. Setting the background size to cover would mean that the background image would be scaled (stretched) to fit the size of the container element.
Here is what MDN says about background-size: cover:
Scales the image as large as possible and maintains image aspect ratio (image doesn't get squished). The image "covers" the entire width or height of the container.
If you want the background image to remain constant even when scrolling down the page, you should add background-attachment: fixed to the element. This would keep the image in its place.
The background-position: 50% 50% in the below snippet is an optional setting which is just used to keep the background image positioned at the center-mid. This can be avoided if such a positioning is not required. By default the image would get positioned at top-left.
body {
background-image: url("http://lorempixel.com/850/420/nature/1");
background-position: 50% 50%;
background-attachment: fixed;
background-size: cover;
background-repeat: no-repeat;
}
div{
height: 100px;
}
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
Note that stretching happens with background-size: cover only when the background-attachment: fixed setting is not applied (meaning, the image is not constant and gets stretched to fit container's full height/width) or when the image is smaller than the container. When it is larger than the container and background-attachment: fixed setting is applied, the image does not get stretched.
Another thing to note with background-size: cover is that when the image and the container have different sizes, the image is clipped at the sides. If it should be shrunk instead of being clipped then background-size: 100% 100% could also be used.
body {
background-image: url("http://lorempixel.com/850/420/nature/1");
background-position: 50% 50%;
background-attachment: fixed;
background-size: 100% 100%;
background-repeat: no-repeat;
}
div{
height: 100px;
}
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>
<div>Lorem Ipsum Dolor Sit Amet......</div>

Related

Bootstrap: Two columns inside container, but one should break the container

I am using latest version of bootstrap and have a design with 2 columns where the first column should contain some text and the second column should contained a background image which fills the whole column up to the users right screen. I want the background image to go outside the column to the right, until it reaches the edge of the browser.
like this:
how can i make second column to go outside the container? That's what i am currently using which is not working (image gets cut off by container)
<div class="container">
<div class="row">
<div style="" class="col-sm-12 col-lg-6">
<p>Example text</p>
</div>
<div class="col-sm-12 col-lg-6 bg-image" style="background-image:url('http://placehold.it/1800x1045');">
</div>
</div>
</div>
Try adding a contain value to the background image.
style="background-image: url('http://placehold.it/1800x1045'); background-size: contain;"
You can create the main container as "container-fluid" to fill the entire page content and then create the columns, one other container with your text and the other with the image, check the code below, ignore the height and the borders because I was trying to create your scenario:
<html>
<head>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid" style="height: 500px;">
<div class="row h-100">
<div class="col-sm-6" style="border: 1px solid pink;">
<div class="row">
<div class="container">
<div style="border: 1px solid blue;" class="col-sm-6 col-lg-6">
<p>Example text</p>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-lg-6 no-gutters bg-image" style="background-image:url('https://dummyimage.com/600x400/666/fff'); border: 1px solid red;">
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
</body>
</html>
What you are trying to do is not contemplated by Bootstrap, but you can use a workaround. Why it is not contemplated? Because for a 2 column layout, it uses up 50% of the div, and you are not asking for a 50/50 layout.
First of all, the container, fluid or not, doesn't entirely touch the side of the page. Also, in both cases it is symetrical, and your design is not.
So... what you want to do is a greater div that occupies 100% of the page, with a container (fluid or not) in it. With absolute positioning, you create another div that occupies 50% of the greater div, and has the image as background.
.greater-container {
position: relative; //needed so that the .image-container can be properly positioned
}
.image-container {
position: absolute;
top: 0;
bottom: 0;
left: 50%;
right: 0;
background-color: green;
background-image: url('http://placekitten.com/g/1800/1045');
background-size: cover;
z-index: 0;
}
.content-column {
border: 1px solid red; //so that we can see it
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="greater-container">
<div class="image-container"></div>
<div class="container">
<div class="col-sm-6 content-column">
Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet. Lorem ipsum sid dolor amet.
</div>
</div>
</div>
As a sidenote, this is not an easy layout for a responsive website. That background-image will get resized a lot and will probably not always work well.

CSS Grid - alternate order of elements only on Desktop

I want to make an adaptive page with CSS grid like this for PC:
IMG | Text
Text | IMG
IMG | Text
And like this for mobile:
IMG
Text
IMG
Text
IMG
Text
The problem is I can not wrap each pair Text IMG to a div.
How can I make such layout with that chess order and without it for mobile?
img {
max-width: 100%;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
}
#media screen (max-width: 540px) {
.grid {
grid-template-columns: 1fr;
}
}
<div class="grid">
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
</div>
You can adjust the placement using grid-column:
img {
max-width: 100%;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-auto-flow:dense; /* Don't forget this to fill all the tracks */
}
/* you pattern repeat each 4 elements */
.img:nth-child(4n + 2) {
grid-column:1;
}
.info:nth-child(4n + 1) {
grid-column:2;
}
/**/
#media screen and (max-width: 540px) {
.grid {
grid-template-columns: 1fr;
}
.info:nth-child(4n + 1) {
grid-column:1;
}
}
<div class="grid">
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
<div class="info">
<h2>Lorem, ipsum.</h2>
<p>Lorem ipsum dolor sit amet.</p>
<button>Lorem.</button>
</div>
<div class="img">
<img src="https://via.placeholder.com/350x150" alt="">
</div>
</div>

Cut div at bottom of page

Im using bootstrap 4.0.0-beta.2 and I have a css problem.
I want following layout
This is the html:
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"/>
<div id="task" class="container">
<div class="row">
<div class="col-12">
<div class="card card-shadow">
<div class="card-header accent-color">
FOOOOOOOO
</div>
<div class="card-body">
<h4 class="card-title">BAAAR</h4>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id consectetur lorem, quis mattis orci.</p>
Go somewhere
</div>
</div>
</div>
<div class="col-12">
<div class="card card-shadow" id="paint">
<div class="card-header accent-color">
paint
</div>
<div class="card-body">
<app-paint></app-paint>
</div>
</div>
</div>
</div>
</div>
And what im trying to create is a layout of cards.
I want the first card to stay within the col-12 width and adapt the hight after content. And then I want the second div to always end at bottom of page. No margin between. So I tried to add position:fixed, bottom:0 and height:100% but then the width get wierd and it cant handle resize of the page. So How can I force the second div to end at page bottom?
You may use height and margins.
Boostrap class: .h-100 sets height:100% , but parent need an height where % can be calculated from (css added for html & body)
margin-top:auto and bottom 0 will send the second element at the bottom. boostrp classes used : mt-auto mb-0
html,
body {
height: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" />
<div id="task" class="container h-100"><!-- class added -->
<div class="row h-100"><!-- class added -->
<div class="col-12">
<div class="card card-shadow">
<div class="card-header accent-color">
FOOOOOOOO
</div>
<div class="card-body">
<h4 class="card-title">BAAAR</h4>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id consectetur lorem, quis mattis orci.</p>
Go somewhere
</div>
</div>
</div>
<div class="col-12 mb-0 mt-auto"><!-- class added -->
<div class="card card-shadow" id="paint">
<div class="card-header accent-color">
paint
</div>
<div class="card-body">
<app-paint>app-paint</app-paint>
</div>
</div>
</div>
</div>
</div>
or do you need the second div to expand ?
html,
body {
height: 100%;
}
.custom-flex {
flex: 1;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet" />
<div id="task" class="container flex-column h-100">
<!-- class added -->
<div class="d-flex flex-column h-100">
<div class="">
<div class="card card-shadow">
<div class="card-header accent-color">
FOOOOOOOO
</div>
<div class="card-body">
<h4 class="card-title">BAAAR</h4>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id consectetur lorem, quis mattis orci.</p>
Go somewhere
</div>
</div>
</div>
<div class="d-flex flex-column custom-flex">
<div class="card card-shadow custom-flex" id="paint">
<div class="card-header accent-color">
paint
</div>
<div class="card-body">
<app-paint>app-paint</app-paint>
</div>
</div>
</div>
</div>
</div>
I think the answer of this question would be to change the css of the card. If you are looking for to increase or decrease the space between the cards from top or from bottom you should change the css like so:
In your case for card shadow it would be
.d-flex [class*='card-shadow'] {
margin-top: 2.5em;
margin-bottm: 2.5em;
}
Use your own unit for css calculation em, px or whatever suit you.

CSS Flexbox - make elements containing other elements same height

I am trying to create a layout using Flexbox where I have elements which consist of 3 other internal elements. The parent item element contains 3 divs: image, button, text. The issue is that my items will not always contain images or text that is the same height as the others. The button is the one thing that will have a consistent height. I am trying to figure out if it's possible to have each of my image divs be the same height as the tallest one and same for the text divs. I would also like the images to be vertically aligned to the bottom, so if one element has a shorter image, the white space to make the element the same height will go above the image like this:
And here is what I have so far:
.container {
display:flex;
flex-wrap:wrap;
flex-flow:row wrap;
justify-content:center;
}
.item {
max-width:200px;
margin:0 20px;
}
<div class="container">
<div class="item">
<div class="image">
<img src="http://placehold.it/150x300" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>consectetur adipiscing elit.</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x200" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x250" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x270" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</div>
I know that I could do this using Javascript to loop through each item to get the tallest and change the CSS of all others, but I'd like to use only CSS if possible. I also know that I could just set the height of the image container to the height of the tallest image, but these images are going to be dynamic and there are going to be a lot of them, so I'd rather have a solution that doesn't require hardcoding values.
Flexing the .item class and adding justify-content: flex-end; would provide the majority of the affect, but as far as I know you'd have to set a specific height on at least one of the items if you want two elements to be aligned the same across flexbox. Happy to be proven wrong though.
You could alternatively use margin-top: auto on the first child to push any unused space to the top and everything else down.
.container {
display:flex;
flex-wrap:wrap;
flex-flow:row wrap;
justify-content:center;
}
.item {
max-width:200px;
margin:0 20px;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.text {
height: 36px; /* magic number */
}
<div class="container">
<div class="item">
<div class="image">
<img src="http://placehold.it/150x300" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>consectetur adipiscing elit.</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x200" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x250" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
<div class="item">
<div class="image">
<img src="http://placehold.it/150x270" />
</div>
<div class="button">
<button>Click Me</button>
</div>
<div class="text">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
</div>

Is there a way in Bootstrap to "split" a column on small screens?

I'm using Bootstrap 3.
On large screens I want to have a sidebar on the left and the maincontent on the right. On small screens I want to have important blocks of the sidebar on top, then the maincontent, then the less important blocks of the sidebar. Is there a way to achieve that?
Here's a JS Bin showing the problem: http://jsbin.com/wibucopi/1/ and below is the current code (which, however, displays all sidebar content on top on small screens).
<div class="container-fluid">
<div class="row">
<div class="col-sm-3">
<div class="upper" style="background:red">
<h3>I want to be <b>above</b> the main content on small screens!</h3>
</div>
<div class="lower" style="background:green">
<h3>I want to be <b>below</b> the main content on small screens!</h3>
</div>
</div>
<div class="col-sm-9">
<h1>Main content</h1>
<p>Lorem ipsum dolor sit amet</p>
</div>
</div>
</div>
I've already played around with col-sm-pull/push-x, but I could only achieve that the whole sidebar is displayed below the maincontent on small screens.
I don't want to duplicate content and show / hide it with visible-XY, hidden-XY, as the page would get bigger and it feels just wrong.
It would be great to have a pure Bootstrap css solution, or at least a css only one (I wouldn't like to use js).
You could do something like this:
Bootply Demo
HTML:
<div class="container-fluid">
<div class="row">
<div class="upper col-sm-3" style="background:red">
<h3>I want to be <b>above</b> the main content on small screens!</h3>
</div>
<div class="col-sm-9 col-sm-pull-right">
<h1>Main content</h1>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
<p>Lorem ipsum dolor sit amet</p>
</div>
<div class="lower col-sm-3" style="background:green">
<h3>I want to be <b>below</b> the main content on small screens!</h3>
</div>
</div>
</div>
CSS:
#media (min-width: 768px) {
.col-sm-pull-right {
float: right;
}
}
.lower {
clear: left;
}

Resources