Background image cover does not scale the image down - html

I've got a calendar div (that actually has height and width set to 100vh and 100vw to be fullscreen) containing a header and an actual calendar.
I use flex because I want the header to have a specific height, and the contained calendar to take all the vertical space it has left.
rbc-calendar is actually an external library I use (React Big Calendar) which uses flex on its own to scale the rows. I've put the main div css in case it comes in relevant.
I want my calendar container to have a background image. So only for the calendar itself, not the header. I want this image to be scaled down until the height (width) fits the calendar's height (weight), keeping the image's aspect ratio and letting it overflow for the same amount on right/left (top/bottom).
Background-image: cover seems to be what I'm looking for, but for some reasons the image does not get scaled down at all.
.calendar {
height: 333px;
width: 333px;
display: flex;
flex-direction: column;
}
.calendar-header {
height: 40px;
display: flex;
justify-content: center;
align-items: center;
background: lightblue;
}
.calendar-container {
flex: 1;
background-size: cover;
background: #000 url('https://www.chenhuijing.com/slides/29-constellation-2018/img/meme1.jpg') no-repeat center center;
}
.rbc-calendar {
height: 100%;
display: flex;
align-items: stretch;
}
<div class="calendar">
<div class="calendar-header">
<h1>Not working calendar</h1>
</div>
<div class="calendar-container">
<div class="rbc-calendar">
</div>
</div>
</div>

Answer in the question's comments by Temani-afif : setting background after background-size overrides the statement.

Related

How to hide borders when resizing images?

I put three photos inside a container but since I want there to be space between them, I couldn't leave the original size because they would take up the whole container without leaving the space I want.
To make them smaller I modified the height to 80%.
It worked but since I need to add the shadow to the box, I need it to match the edges of the image.
As you can see from the purple, the box is larger than the actual image. I would like to know how to get a box as big as the actual image, so without the purple section.
I added the background color only to the first pic, but the problem can be extended for all the three pics.
I post the code below.
.background {
height: 100vh;
display: flex;
justify-content: space-between;
}
.background * {
width: 100%;
height: 80%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
<div class="background">
<div class="firstphoto"></div>
<div class="secondphoto"></div>
<div class="thirdphoto"></div>
</div>
Thanks all! ;)
You can take a look at object-fit property: https://www.w3schools.com/css/css3_object-fit.asp
Also, you should put:
.background > * {
flex: 1/3;
}
So that the boxes are taking the same space.
you should add this to each div that contains an image (if they have the same class)
The div would then be positoinned relatively to the image and you could then edit the box-shadow with the box-shadow property
.col{
position:relative;
top:0px;
left:0px;
width:100%;
height:100%;
margin-right:3.33%;
box-shadow: 10px 10px 10px 10px red;
}
Not sure why you're having the images as background images, but I would just use object-fit. Do note, I replaced the divs with image tags.
.background {
height: 100vh;
display: flex;
justify-content: space-between;
}
.background img {
width: 100%;
height: 80%;
padding: 1rem;
box-sizing: border-box;
object-fit: contain;
}
<div class="background">
<img src="https://picsum.photos/200/300" alt="200x300" title="200x300"/>
<img src="https://picsum.photos/50/150" alt="50x150" title="50x150"/>
<img src="https://picsum.photos/30/150" alt="30x150" title="30x150"/>
</div>

Flex item size from background image

there is a flexbox with flex items
every flex item should be shown as a clickable folder with particular text in it
as far as I understand, the only way to achieve that via CSS is to have a background image
The problem is that I want to get the following as well:
Constraint every flex item, ideally only by the width, e.g. max-width: 20% (to show it nicely on mobile)
Let flex items automatically expand their width/height to show a complete background image (preserving the constraint above)
Unfortunately, was unable to find a right combination of params for that, so far it looks like this:
<div class="container">
<div class="column">
name1
</div>
<div class="column">
name2
</div>
</div>
.container {
height: 100vh;
display: flex;
flex-flow: row wrap;
align-items: center;
}
.column {
max-width: 20%;
background-image: url("./ic-folder.png");
background-size: contain;
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: space-around;
This doesn't achieve the goal - looks like every item is large enough just to cover nested <a> and they don't care about background there, so, they are smaller than desired.
I have an assumption that in this particular case we can hard-code the item's size as background image size, but that means that every time the background image is changed, we need to adjust the css with its new dimensions.
Is there any CSS way to force the element to grow in a way to cover its background image?
I think instead of adding the image in the background-image you can put it inside of the element. When you do this image will be clickable. Also if you use the style code that I wrote for the img you create a responsive image. If you want to control the image size you can play with its parent div with this way you can manage to control the width. So I suggest you give what width that you want to the .column and control your width and image problem.
.container {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.column {
display: flex;
align-items: center;
justify-content: center;
margin: 10px;
max-width: 20%;
/* background-image: url("https://t1.thpservices.com/previewimage/gallil/bbd632f2f8bb5df1c8f8aba51a0ef5dd/esy-008887292.jpg");
background-size: contain;
background-repeat: no-repeat; */
}
img {
max-width: 100%;
height: auto;
object-fit: contain;
}
#media screen and(max-width: 450px) {
.container {
flex-direction: column;
}
}
<div class="container">
<div class="column">
<a href="path1"
><img
src="https://t1.thpservices.com/previewimage/gallil/bbd632f2f8bb5df1c8f8aba51a0ef5dd/esy-008887292.jpg"
alt=""
/>name1</a
>
</div>
<div class="column">
<a href="path2"
><img
src="https://t1.thpservices.com/previewimage/gallil/bbd632f2f8bb5df1c8f8aba51a0ef5dd/esy-008887292.jpg"
alt=""
/>name2</a
>
</div>
</div>

Image (.svg) doesn't extend over the entire width of the page

I made an SVG image, but when I add it to a page and set the width value to 100%, it still doesn't extend over the entire width of the page, there is still small gaps that remain at the edges.
I tried to change value to 100vw but then the image is widther.
When I fullscreen the page then everything is okay.
IMG
HTML:
<footer>
<div class="footer-top-shape">
<img class="footer-top-shape-img" src="./svgs/footershape26.svg" alt="Footer shape">
</div>
<div class="footer-container">
<div class="footer-content">
CSS:
footer{
height: auto;
width: 100%;
background-color: #0a2233;
}
.footer-top-shape-img{
width: 100%;
height: auto;
}
.footer-container{
width: 100%;
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
}
I suppose you are using Chrome. The problem could be then in the way (bug if you want) the Chrome processes .svg because FF seems to show it correctly without any margins.
I've found this answer: background-size:100% 100%; doesn't work properly in Chrome
Edit your .svg and add the property preserveAspectRatio="none" into the <svg> element.

Resizing flex div image instead of cropping

I have a flex with 3 images and I would want them resize if a window is too small right now when window gets smaller first they reorder so they stack vertically and when window gets even smaller the picture gets squeezed instead of resized I would want to keep the image with proper aspect ratio.
.images {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.images div {
display: flex;
margin: 1rem;
}
.images img {
height: 16rem;
max-width: 100%;
}
<div class="images">
<div>
<img src="http://placehold.it/150x200">
</div>
<div>
<img src="http://placehold.it/150x150">
</div>
<div>
<img src="http://placehold.it/150x100">
</div>
</div>
First of all the basic thing to keep in mind to maintain aspect ratio (I'm sure you already know this) is to restrict only one dimension of an image. (Read this)
You are already breaking this in your code- resulting in the 'squeeze' at smaller screen widths:
.images img {
height: 16rem;
max-width: 100%;
}
When window gets smaller first they reorder so they stack vertically
and when window gets even smaller the picture gets squeezed instead of
resized I would want to keep the image with proper aspect ratio.
So here are your options:
So I guess you should remove max-width: 100% and keep width adjust depending on the 16rem height.
.images {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.images div {
display: flex;
margin: 1rem;
}
.images img {
height: 16rem;
/*max-width: 100%;*/
}
<div class="images">
<div>
<img src="http://placehold.it/150x200">
</div>
<div>
<img src="http://placehold.it/150x150">
</div>
<div>
<img src="http://placehold.it/150x100">
</div>
</div>
Well, for small widths you would have horizontal scroll. According to the particular case, if needed you can use some media queries to adjust height at small screen widths.
Let me know your feedback on this. Thanks!
.images img{
height: 16rem;
max-width: 100%;
object-fit: contain;
}
For the aspect ratio fix, you can just run with the CSS3 object-fit property. CSS3 Object-Fit
Set it on your image as:
.images img {
object-fit: contain;
}
That should do the trick of keeping the aspect ratio of the image.
As for the Wrapping that takes place within the flex container, just take out the flex-wrap property in your code so they'll all stay on the same row, rather than wrapping as the container size gets smaller.
EDIT
Try adding a align-self CSS Property to the .images img, see if that's what you're looking for:
.images {
display: flex;
justify-content: center;
flex-wrap: wrap;
}
.images div {
display: flex;
margin: 1rem;
}
.images img {
width: 100%;
height: auto;
object-fit: contain;
align-self: flex-start;
}
Hope this helps!

Div width 100% minus fixed amount of pixels

How can I achieve the following structure without using tables or JavaScript? The white borders represent edges of divs and aren't relevant to the question.
The size of the area in the middle is going to vary, but it will have exact pixel values and the whole structure should scale according to those values. To simplify it, I'd need a way to set "100% - n px" width to the top-middle and bottom-middle divs.
I'd appreciate a clean cross-browser solution, but in case it's not possible, CSS hacks will do.
Here's a bonus. Another structure I've been struggling with and end up using tables or JavaScript. It's slightly different, but introduces new problems. I've been mainly using it in jQuery-based windowing system, but I'd like to keep the layout out of the script and only control the size of one element (the middle one).
New way I've just stumbled upon: css calc():
.calculated-width {
width: -webkit-calc(100% - 100px);
width: -moz-calc(100% - 100px);
width: calc(100% - 100px);
}​
Source: css width 100% minus 100px
You can use nested elements and padding to get a left and right edge on the toolbar. The default width of a div element is auto, which means that it uses the available width. You can then add padding to the element and it still keeps within the available width.
Here is an example that you can use for putting images as left and right rounded corners, and a center image that repeats between them.
The HTML:
<div class="Header">
<div>
<div>This is the dynamic center area</div>
</div>
</div>
The CSS:
.Header {
background: url(left.gif) no-repeat;
padding-left: 30px;
}
.Header div {
background: url(right.gif) top right no-repeat;
padding-right: 30px;
}
.Header div div {
background: url(center.gif) repeat-x;
padding: 0;
height: 30px;
}
While Guffa's answer works in many situations, in some cases you may not want the left and/or right pieces of padding to be the parent of the center div. In these cases, you can use a block formatting context on the center and float the padding divs left and right. Here's the code
The HTML:
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
</div>
The CSS:
.container {
width: 100px;
height: 20px;
}
.left, .right {
width: 20px;
height: 100%;
float: left;
background: black;
}
.right {
float: right;
}
.center {
overflow: auto;
height: 100%;
background: blue;
}
I feel that this element hierarchy is more natural when compared to nested nested divs, and better represents what's on the page. Because of this, borders, padding, and margin can be applied normally to all elements (ie: this 'naturality' goes beyond style and has ramifications).
Note that this only works on divs and other elements that share its 'fill 100% of the width by default' property. Inputs, tables, and possibly others will require you to wrap them in a container div and add a little more css to restore this quality. If you're unlucky enough to be in that situation, contact me and I'll dig up the css.
jsfiddle here: jsfiddle.net/RgdeQ
Enjoy!
You can make use of Flexbox layout. You need to set flex: 1 on the element that needs to have dynamic width or height for flex-direction: row and column respectively.
Dynamic width:
HTML
<div class="container">
<div class="fixed-width">
1
</div>
<div class="flexible-width">
2
</div>
<div class="fixed-width">
3
</div>
</div>
CSS
.container {
display: flex;
}
.fixed-width {
width: 200px; /* Fixed width or flex-basis: 200px */
}
.flexible-width {
flex: 1; /* Stretch to occupy remaining width i.e. flex-grow: 1 and flex-shrink: 1*/
}
Output:
.container {
display: flex;
width: 100%;
color: #fff;
font-family: Roboto;
}
.fixed-width {
background: #9BCB3C;
width: 200px; /* Fixed width */
text-align: center;
}
.flexible-width {
background: #88BEF5;
flex: 1; /* Stretch to occupy remaining width */
text-align: center;
}
<div class="container">
<div class="fixed-width">
1
</div>
<div class="flexible-width">
2
</div>
<div class="fixed-width">
3
</div>
</div>
Dynamic height:
HTML
<div class="container">
<div class="fixed-height">
1
</div>
<div class="flexible-height">
2
</div>
<div class="fixed-height">
3
</div>
</div>
CSS
.container {
display: flex;
}
.fixed-height {
height: 200px; /* Fixed height or flex-basis: 200px */
}
.flexible-height {
flex: 1; /* Stretch to occupy remaining height i.e. flex-grow: 1 and flex-shrink: 1*/
}
Output:
.container {
display: flex;
flex-direction: column;
height: 100vh;
color: #fff;
font-family: Roboto;
}
.fixed-height {
background: #9BCB3C;
height: 50px; /* Fixed height or flex-basis: 100px */
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
.flexible-height {
background: #88BEF5;
flex: 1; /* Stretch to occupy remaining width */
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}
<div class="container">
<div class="fixed-height">
1
</div>
<div class="flexible-height">
2
</div>
<div class="fixed-height">
3
</div>
</div>
The usual way to do it is as outlined by Guffa, nested elements. It's a bit sad having to add extra markup to get the hooks you need for this, but in practice a wrapper div here or there isn't going to hurt anyone.
If you must do it without extra elements (eg. when you don't have control of the page markup), you can use box-sizing, which has pretty decent but not complete or simple browser support. Likely more fun than having to rely on scripting though.
Maybe I'm being dumb, but isn't table the obvious solution here?
<div class="parent">
<div class="fixed">
<div class="stretchToFit">
</div>
.parent{ display: table; width 100%; }
.fixed { display: table-cell; width: 150px; }
.stretchToFit{ display: table-cell; vertical-align: top}
Another way that I've figured out in chrome is even simpler, but man is it a hack!
.fixed{
float: left
}
.stretchToFit{
display: table-cell;
width: 1%;
}
This alone should fill the rest of the line horizontally, as table-cells do. However, you get some strange issues with it going over 100% of its parent, setting the width to a percent value fixes it though.
We can achieve this using flex-box very easily.
If we have three elements like Header, MiddleContainer and Footer. And we want to give some fixed height to Header and Footer. then we can write like this:
For React/RN(defaults are 'display' as flex and 'flexDirection' as column), in web css we'll have to specify the body container or container containing these as display: 'flex', flex-direction: 'column' like below:
container-containing-these-elements: {
display: flex,
flex-direction: column
}
header: {
height: 40,
},
middle-container: {
flex: 1, // this will take the rest of the space available.
},
footer: {
height: 100,
}
what if your wrapping div was 100% and you used padding for a pixel amount, then if the padding # needs to be dynamic, you can easily use jQuery to modify your padding amount when your events fire.
I had a similar issue where I wanted a banner across the top of the screen that had one image on the left and a repeating image on the right to the edge of the screen. I ended up resolving it like so:
CSS:
.banner_left {
position: absolute;
top: 0px;
left: 0px;
width: 131px;
height: 150px;
background-image: url("left_image.jpg");
background-repeat: no-repeat;
}
.banner_right {
position: absolute;
top: 0px;
left: 131px;
right: 0px;
height: 150px;
background-image: url("right_repeating_image.jpg");
background-repeat: repeat-x;
background-position: top left;
}
The key was the right tag. I'm basically specifying that I want it to repeat from 131px in from the left to 0px from the right.
In some contexts, you can leverage margin settings to effectively specify "100% width minus N pixels". See the accepted answer to this question.