Items don't zoom when using Flexbox with Browser Zoom - css

I've inherited a site that uses Flexbox to achieve a basic 2 column layout. A user has noted that when you use the zoom feature of your browser the content around the flex displayed items zooms, but the flex items themselves actually shrink.
I have attempted to use flex-shrink set to 0, but that does not seem to solve the issue.
Here is a codepen illustrating the issue. https://codepen.io/anon/pen/owGmEd
I'm trying to figure out if it's possible to use flexbox and still have browser zoom work as users expect. I could rewrite the code to ditch flexbox, but that seems like a heavy handed approach.
div {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
margin-top: 60px;
}
img {
width: 50%;
height: 100%;
max-height: 100%;
max-width: 100%;
flex-shrink: 0;
}
<div>
<img src="http://placeholder.pics/svg/300x444" />
<img src="http://placeholder.pics/svg/300x444" />
</div>

Related

Wrapping a link around an image destroys flexbox layout and causes browser rendering quirks

Struggling to find the right title that isn't just a mixture of "help" and "what, CSS, why?!" so hopefully a couple of you geniuses will find this...!
I have two columns. Each of them has a full-width div inside it which contains a logo. The images are quite different shapes, one being a square and one being a more panoramic aspect ratio. To achieve a balanced look, the images are set to a max-width of 50% and a max-height of 100%. Flexbox is used to center the images both horizontally and vertically.
They look perfectly fine.
// working before wrapping images with links
section.working {
div.flex {
display: flex;
justify-content: center;
align-items: center;
img {
max-width: 50%;
max-height: 100%;
}
}
}
And then I needed to add links.
https://codepen.io/lenoz/pen/VwZyeOG
This is the problem reduced to its most simple, in that the bottom row was the original code I was using to get the perfect layout, and the top row shows what happens when the images were wrapped in tags to make them links. Some points of note:
colours added just to help distinguish boundaries a little - useful for detecting when the link (red background) is no longer constricted to the size of the image inside it (as it ideally should be)
the two columns are separate in the code and not part of a shared container - i.e. one cannot inform the height of the other (want to fix this with CSS not JS)
I should mention that of course there was no way adding links would just work - the <a> tags come in between the flex container and the flex item, so obviously they will mess with the layout.
Much appreciated if you can help me find a CSS solution.
Still here? Read on if you want some more info on my attempts to fix, with a side portion of Chrome weirdness.
It should also go without saying I've spent ages fiddling with this, so here's another link showing some of my efforts that have gotten close: https://codepen.io/lenoz/pen/pozpjVq
The top row (section.help) is my latest attempt, but is a bit of a mess simply because I stopped half way, having suffered frustration sufficient to lead to me making this post.
The middle row, which I'm calling section.weirdness, actually seemed to be a solution for a hot minute. If you're using Chrome, like I am, when you look at the Codepen link you may see nothing on these blue blocks?
But try removing the display: flex attribute from div.flex and, if your Chrome is like my Chrome, you'll see this:
Now, add that same display: flex attribute back on the same div.flex selector and you'll see that suddenly the blue blocks are not blank:
How strange is that? Browser rendering bug or what?
Now find the max-width or max-height attributes on div.image, toggle one of those off and then on again and you'll see that everything suddenly looks right again:
Somehow, without changing any CSS other than toggling it, we've gone from no links showing up at all, to them showing up and looking perfect. You can see how I'd managed to confuse myself into thinking I had got it working!
Just add style="display: contents" to your anchors
"display: contents" causes an element's children to appear as if they were direct children of the element's parent, ignoring the element itself
<div>
<a style="display: contents" href="#">
<img src="https://via.placeholder.com/1000x300.png" />
</a>
</div>
Here's a simple solution:
I've changed the columns to be flex contexts but retained an inner div to serve as the 50% width constraint. When the imgs are allowed to set their own height explicitly all the other constraints around them flow into place without much fuss, and because the anchors don't have any layout rules, they manage to avoid having any clickable areas outside their image.
With the same max-height on the images, they'll match in the same way as your .working class as long as their containers are the same width.
section {
width: 800px;
display: flex;
}
.column {
background-color: blue;
margin: 5px;
width: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.column > div {
max-width: 50%;
}
img {
display: block; /* get rid of bottom gap */
max-width: 100%;
max-height: 80px;
}
<section>
<div class="column">
<div>
<a href="#">
<img src="https://via.placeholder.com/500x500.png" />
</a>
</div>
</div>
<div class="column">
<div>
<a href="#">
<img src="https://via.placeholder.com/1000x300.png" />
</a>
</div>
</div>
</section>
Try adding this to your Codepen example:
.flex > a {
flex: 0 0 50%;
height: 100%;
display: flex;
}
div.flex a > img {
max-width: 100% !important;
max-height: 100% !important;
margin: auto;
}
Any immediate child of a container with display: flex is flex item. To prevent that item from growing or shrinking we must set flex-grow and flex-shrink properties to 0. In my case I used flex: 0 0 50% shorthand for that. That last value of 50% is from your initial image max-width property. That + height:100% will make sure that <a> behaves like images in your original example.
Now the fun part: use display: flex again on <a> to make the image flex item again. Since <a> is already properly sized we can set max-width and max-height to `00% to fill available space.
Using margin: auto is a neat trick to center both horizontally and vertically flex child inside of flex container (works only when there is one child).
sidenote: I used important to override specificity without changing markup but I would advise against it and put new CSS class on both a and img.
UPDATE
working fork (Chrome only): https://codepen.io/teodragovic/pen/wvwpWbx?editors=1100
section.broken {
.flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
a {
max-width: 50%;
max-height: 100%;
}
img {
max-width: 100%;
max-height: 100%;
display: block;
}
}

Angular Material mat-drawer in full height flex, content overflow auto

Yesterday I faced a CSS issue which seems to be related to mat-drawer and Angulars router-outlet. I have got a fullpage flexbox with two children. A mat-toolbar at the top and a custom component app-sidenav at the bottom. This works fine and the app-sidenav fills the rest of the page since the flexbox is stretchy. Have a look at this simplified setting before continue:
<div class="flex">
<mat-toolbar></mat-toolbar>
<app-sidenav></app-sidenav>
</div>
The related css is
.flex { width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: stretch; }
mat-toolbar { flex: 0 0 auto; }
app-sidenav { flex: 1 1 0; }
In the app-sidenav component I now have the following template
<mat-drawer-container>
<mat-drawer></mat-drawer>
<mat-drawer-content>
<main><router-outlet></router-outlet></main>
</mat-drawer-content>
</mat-drawer-container>
And the related styles are
mat-drawer-container, mat-drawer-content { display: block; height: 100%; }
main { height: 100%; overflow-y: auto; }
This works fine and the height is appropriate unless there is no content larger than the app-sidenav height. The scrollbar appears at the outer flexbox component and not at the main-tag. I also tested !important at the heights and also 100vh but with no success. So how can I get the overflow-y at the main tag working?
I'm pretty sure that there is a simply trick, but I can't get it for know. Thanks for your help.
Cheers!
Edit:
I made a stackblitz for this issue. When you navigate to the ciao component you see that the scrollbar appears at the document root and not in the main tag.
In addition to #Sakkeer's working solution I found another way without hacking the position attribute but with usage of flex. Just add (not replace) the following css rules to the existing styles.
app-sidenav { display: flex; }
mat-drawer-container { flex: 1 1 auto; }
Try this for main css class
main {
position: absolute;
right: 0px;
left: 0px;
bottom: 0px;
top: 0px;
}
This worked for me!add it to style.scss:
.mat-drawer-inner-container{ overflow: hidden !important; }
if it doesn't work for you, try below in style.scss:
*{ overflow: hidden !important; }
<mat-drawer-container autosize style="position: absolute;right: 0px;left: 0px;bottom: 0px;top: 0px;">
<mat-drawer #drawer mode="side" class="toolbar">
<app-sidenav></app-sidenav>
</mat-drawer>
<router-outlet></router-outlet>
</mat-drawer-container>
Above code just worked for me, when I put style directly and use autosize so that mat-drawer-container will not overlap on the router page.
It will add two scrollbar. One for main page scroll and another scrollbar is for the mat-draw which slide from left. The mat-draw will have its own scroll bar. Just like the screenshot.
.mat-drawer.mat-drawer-end {
position: fixed;
overflow: auto;
}
Beside having long page i can see the mat-draw on the top with its own scroll. I hope this helps with minimal code require to achieved what we want.

Image as a flex item not scaling with max-width in Chrome

I have an image within a flex container.
The image stays at its original height in Chrome and will not resize proportionally. It works in Firefox however.
<figure>
<img src="image.jpg">
A link to somewhere
</figure>
figure {
display: flex;
width: 100%;
}
figure img {
max-width: 50%;
height: auto;
}
Flex makes its children equal in height by default. To disable this behavior, you can specify align-items: flex-start.
https://jsfiddle.net/3s2hLv92/1/

CSS: Sticky Footer using Flexbox – avoiding the vh unit by setting percentages?

I am experimenting with using Flexbox to implement a sticky footer (footer is at the bottom of the page, even when there is little content).
I found a great example of this on the web:
HTML:
<body class="Site">
<header>...</header>
<main class="Site-content">...</main>
<footer>...</footer>
</body>
CSS:
.Site {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.Site-content {
flex: 1;
}
Fiddle
Note: Won't work in all browsers because of unprefixed declarations, maybe try it in Chrome
While this works I don't like the use of the vh unit because that unit is even less suported than Flexbox. So I tried to use percentages instead of vh:
body {
display: flex;
min-height: 100%;
flex-direction: column;
}
Fiddle
(To keep it short I only post the code that changed, but a full example is in the Fiddle.)
Now the solution is not working anymore because the body's parent – the html element – has no height declared, so min-height has no reference. So I've tried to set
html,
body {
min-height: 100%;
}
but that also did nothing. Probably because that way, also the html element has no reference. As a conclusion, I have to do it like this to get it working again:
html {
height: 100%;
}
body {
display: flex;
min-height: 100%;
flex-direction: column;
}
Fiddle
While this seems to work, I am not sure of the side effects of using height: 100% on the html element. I remember some years back, I once rendered a website unusable by using something similar without the matching overflow declaration.
Are there any downsides of this solution? Are there maybe more robust solutions using percentages?

display: table-cell centering with two elements, rather than three

I have a working example of vertically centering elements of unknown height, using three elements:
<section>
<div>
<img src="http://placehold.it/100x100"/>
</div>
</section>​
And the CSS:
section {
display: table;
width: 100%;
height: 100%;
position: absolute;
text-align: center;
}
div {
display: table-cell;
vertical-align: middle;
}
There's also a JSFiddle example here: http://jsfiddle.net/Y6KS9/
However I'd like to avoid using unnecessary wrappers if possible. Eg, having the img itself display as table-cell:
div {
display: table;
width: 100%;
height: 100%;
position: absolute;
text-align: center;
}
img {
display: table-cell;
vertical-align: middle;
}
​
However this doesn't work - see the JSFiddle example at http://jsfiddle.net/U2c9R/ - the img is not centered within the div.
Is it possible to vertically center an image of unknown size within its parent using only two elements?
Edit: I'm aware of Flexbox, and intending to throw out the table cell hack completely once IE9 dies. But right now I need to support old browsers.
You could try to use the CSS3 Flexible Box Model.
You should check the browser availability. As you can see by the -webkit vendor prefix my Example currently works only in -webkit-based render engines. But i'm pretty sure it'll work in most modern browsers.
Here is an overview of browsers which supporting the Flexible Box Model: http://caniuse.com/#feat=flexbox
div {
display: -webkit-box;
-webkit-box-pack: center;
-webkit-box-align: center;
height:100%;
width:100%;
position:absolute;
}
Example: http://jsfiddle.net/U2c9R/4/
Update
For Cross-browser support for the CSS3 Flexible Box Model you could use Modernizr and a proper Polyfill which adds support for IE 6-9 and Opera 10.0+. The only hint is, this wouldn't work without JavaScript. But maybe this is an option?

Resources