I'm wondering if someone can help with this problem. I spent a lot of time on it and I'm all out of ideas, I've tried various suggestions from Google results, various combinations of flex grow and shrink, and couldn't get it working.
Demo: https://embed.plnkr.co/dIPh53W4DBkmTB51DCHp/ (open with IE 11)
Edit the code: https://plnkr.co/edit/dIPh53W4DBkmTB51DCHp?p=preview
In this case, in tablet view the <ul> flex width should be 90%, but in desktop view the <ul> flex width should only be 55%. However, we don't want the <ul> in desktop view to be shorter than it is in tablet view, so we set a min-width: 864px on <ul> for desktop view. So if you resize screen between 950px and 970px, the <ul> should no longer shrink suddenly.
This seems to work fine in all of Chrome, Firefox, Safari, and IE10.
But in IE11, the element is the wrong width and won't center as expected. I think it's because at 960px browser dimension, 55% would be max-width: 528px on the <ul> element, but it also has min-width: 864px. For some reason, IE11 renders this as being positioned to the left (instead of the center), with a width of 528px. So IE11 seems to ignore the min-width property, it doesn't handle it like the other browsers.
Code example:
index.html:
<div class="progress-bar">
<ul>
<li>Test item</li>
<li>Test item</li>
<li>Test item</li>
<li>Test item</li>
</ul>
</div>
style.css:
div {
display: flex;
flex-direction: row;
justify-content: center;
}
ul {
display: flex;
flex: 1 1 90%;
max-width: 90%;
margin: 0;
padding: 0;
list-style-type: none;
}
li {
display: flex;
flex: 1 1 0%;
justify-content: center;
margin: 0;
padding: 12px 0;
list-style-type: none;
background: #f7f7f7;
}
#media (min-width: 960px) {
ul {
min-width: 864px !important;
flex-basis: 55%;
max-width: 55%;
}
}
IE 10 actually works fine in this case, so seems that IE 11 release might have broke something that was already working.
Any ideas how this can be resolved?
Since there seems to be no way to resolve this in IE11, I added a temporary media query to change the behavior for the specific dimensions.
In the case where we want 90% width up to 959px screen size, then 55% after 960px screen size -- I did calculation to determine that we want the <ul> element width to be 864px (960px x 90%) when screen is between 960px and 1570px (864px / 55%). So for this dimension range, I force a width and max-width of 864px.
Then for screens larger than 1571px, the flexbox 55% continues to apply again.
Using this method, I can completely ignore min-width.
#media (min-width: 960px) and (max-width: 1570px) {
ul {
flex-basis: 100%;
max-width: 864px;
width: 864px;
}
}
Related
There are a lot of questions about vertical centering, the occasional flexbox-stretching oddity, or the difference between block and table elements, but I couldn't find anything about the (unexpected) behavior of this particular combination.
I'm in a bit of a tricky situation with the markup bootstrap-vue is giving me:
#navbar-container {
/* Given */
position: relative;
display: flex;
width: 100%;
}
#navbar {
/* Given */
flex-grow: 1;
display: flex;
flex-direction: row;
/* For illustration */
background-color: red;
}
.nav-item {
/* Given */
flex-grow: 1;
text-align: center;
/* Added to center .nav-link content vertically */
display: table;
/* Without this Chrome and Edge don't stretch to the height of #navbar(-container), but Firefox does */
/*height: 100%;*/
}
.nav-link {
/* Added to center content vertically */
display: table-cell;
vertical-align: middle;
/* Should cover #navbar's red background */
background-color: lightgreen;
}
<div id="navbar-container">
<div id="navbar">
<div id="brand">
<!-- Gives height to #navbar -->
<img src="https://via.placeholder.com/100">
</div>
<div class="nav-item">
<a class="nav-link">
Item 1
</a>
</div>
<div class="nav-item">
<a class="nav-link">
Item 2
</a>
</div>
<div class="nav-item">
<a class="nav-link">
Item 3
</a>
</div>
</div>
</div>
I'm trying to vertically center the content of .nav-link across the full height of #navbar.
Keep in mind that I can't change anything about the markup here, it's given to me by the framework.
Since #navbar (implicitly) has align-items: stretch, I would assume that .nav-item is stretched to the height of #navbar. Firefox agrees, but Chrome and Edge don't.
The interesting part is that this happens only with display: table elements.
Any other display value (correctly) stretches .nav-item to the height of #navbar.
Note that .nav-link doesn't automatically stretch along in that case, but that's to be expected.
Adding height: 100% to .nav-item fixes the problem, but I can't understand why this is necessary.
I'm not looking for alternative vertical-centering solutions, adding the height works fine.
Using nested flexbox or line-height poses other (architectural) issues.
I suppose at this point I'm mostly curious why this happens, and perhaps more importantly: which browser is in the wrong here?
Here you go with officlal doc.
Table elements have an internal 'table wrapper box'. This wrapper is stretched, but the actual table itself isn't stretched to that box. The table height only grows with its content, or when you specify a height.
It's unclear why, but Firefox apparently does stretch the actual table automatically.
Would love some help from the CSS flex masters out there.
I have a n-count list of 4:3 aspect ratio items which should layout and take the full width of the page.
When the page resizes horizontally the grid of items should wrap.
On a phone, the items should all be one column with their width equal to the phone with minus a little bit of padding.
I've got this which is pretty close: https://codepen.io/kirkouimet/pen/gOLrmvL
ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
li {
margin: 32px;
width: 400px;
height: 300px;
list-style-type: none;
border-radius: 12px;
background: #CCC;
}
The problem I am having is with #3. Some phones have smaller widths than others, so I can't set a fixed width pixel size. Setting a fixed width pixel size is also a problem because I then need to maintain a 4:3 aspect ratio. The items need to have a max width as well so they look good on desktop...
Anyone have ideas on how I could approach this? I think flex and flex wrapping is the way to go. I would like to avoid JavaScript if at all possible as well.
You can use calc() and media-queries in CSS to do so.
#media only screen and (max-width: 550px) {
body {
background-color: #ffe897;
}
li {
width: calc(100vw - 64px);
height: calc(75vw - 64px);
}
}
Here the above media-query will only work if the device width is less or equal to 550px. You can change it as per your need.
The background-color to body is given just to see a when is the media-query start working. You can remove it after you are done with the media-query.
Now is the actual part:
We have assigned width to calc(100vw - 64px). We can do all types of calculation inside calc(). Here 100vw means 100% of the viewport or screen width. We are saying set the width to 100% of the divide width minus 64px which is the margin of 32px on left and right side.
Similarly, the height says 75% of the device with minus the 64px margin.
Check it in action on Codepen Editor: https://codepen.io/manaskhandelwal1/pen/OJbNpqx?editors=1100
Check it in action on Codepen Debug Mode: https://cdpn.io/manaskhandelwal1/debug/OJbNpqx/XxkVwKaqOJxM
To see the width and height calculated by the browser you can use the browser developer tools.
Open the developer tools and change the tab Styles to Computed.
You can see the values change as you change the screen width.
You can have a simplified code like below without media query:
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
li {
margin: 32px;
aspect-ratio:4 / 3; /* this a new property not yet supported everywhere */
width:100%;
max-width: 400px;
list-style-type: none;
border-radius: 12px;
background: #CCC;
}
/* Use the below to support all the browsers
li::before {
content:"";
display:inline-block;
padding-top:75%;
}
*/
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
i want to ask you how can i make a responsive list with 3 items in wich when i reduce the size of my browser the items go vertical and the one is below the other, when the browser window is growing the items will be in one. My code for the list is the following , i managed to order them in center and in one row but i am getting confused about the responsive..
<div class="list">
<ul id="2" class="3">
<li>< </li>
<li> </li>
<li> </li>
</ul>
</div>
and the css
.list{
position: relative;
width: 100%;
display: block;
}
.list li {
width: 33.3%; /* nice 3 columns */
float: left;
padding: 0; /* should have zero paddng/margin */
margin: 0;
}
.list li > span {
margin: 6% 6% 0 0; /* now margins are specified relative to outer <li> width */
display: block;
}
What you are looking for are css media queries. For example, add this to your css:
#media (max-width:500px){
.list li {
float:none;
}
}
Here's a jsfiddle.
Suggest you read this:
https://developers.google.com/web/fundamentals/layouts/rwd-fundamentals/use-media-queries?hl=en
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
http://cssmediaqueries.com/what-are-css-media-queries.html
You can use media queries to set a breakpoint and set the ".list li" width to 100% when the window width is less than the size you want.
Here's a link about media queries: http://cssmediaqueries.com/
I created a break point for my background-image using media queries that starts below 989px (the largest image size). I am not using to display the image because I want to use different images for different devices (So that a mobile device doesn't download the largest image of course). (Each image is defined in a specific break-point). Just to say it early, this is live at http://www.glorkianwarrior.com
The css for this goes like so:
.splash {
max-width: 988px;
margin:auto;
height:380px;
}
#media (min-width: 989px) {
.splash {
background: url('../images/academy.png') no-repeat;
}
}
#media (max-width: 989px) and (min-width: 321px) {
.splash {
background: url('../images/academy-mid.png') no-repeat;
max-width: 640px;
padding: 4px;
position: relative;
background-size: 100%;
}
}
That makes it so once the page reaches 988 px or below (down to 321px), the splash image becomes fluid. It actually doesn't change it's width/height until the browser is less than 640px wide. What happens in the navigation bar below it which is nested under .splash won't change its location. This is because its connected to the height of the .splash. The html looks like so:
<header class="splashhead">
<div class="splash">
<nav class="kochalka">
<ul>
<li class="navclass first active"><a href="http://glorkianwarrior.com/" title="Home" >Home</a></li>
<li class="navclass"><a href="news/" title="News" >News</a></li>
<li class="navclass"><a href="gallery.html" title="Gallery" >Gallery</a></li>
<li class="navclass last"><a href="guide.html" title="Guide" >Guide</a></li>
</ul>
</nav>
</div>
</header>
If I don't give it that height, it will disappear. I have tried giving it 100% or a percentage of the page itself. I tried giving its parent a specific height and then doing 100% on .splash, but that didn't change the placement of the navigation bar.
Is it possible to have this navigation change its size based on browser size? Will I have to figure out a way to use images on the page each image within their own div and use media queries to display:none on non-relevant divs?
You need to wrap your nav within a div and then give it an aspect ration using some clever CSS. See Below -
Here is your code:
I have added a wrapper div around the navas you can see
<header class="splashhead">
<div class="splash">
<div class="wrapper">
<nav class="kochalka" style="">
<ul>
<li class="navclass first active">Home</li>
<li class="navclass">News</li>
<li class="navclass">Gallery</li>
<li class="navclass last">Guide</li>
</ul>
</nav>
</div>
</div></header>
Add the following style also and then it will work as you wish
<style>
.wrapper {
width: 100%;
display: inline-block;
position: relative;
}
.wrapper:after {
padding-top: 56.25%; /*16:9 ratio*/
display: block;
content: '';
}
</style>
Given this markup:
<ul class="grafiek">
<li class="first-child">item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li class="last-child">item</li>
</ul>
How do I make it appear, cross-browser, like so:
In other words: the last item (with the fake pseudo-class last-child) should always stretch to accomodate the cumulative total width of the previous, arbitrary amounts (within reason of course), of <li>'s
This is what I have so far:
ul.grafiek {
float: left;
}
ul.grafiek li {
float: left;
display: block;
margin-left: 6px;
width: 56px;
height: 66px;
padding: 12px 0;
color: #fff;
text-align: center;
font-size: 11px;
line-height: 1;
background-color: #c5015a;
}
ul.grafiek li.first-child {
margin-left: 0;
}
ul.grafiek li.last-child {
clear: both;
margin: 10px 0 0 0;
width: 100%;
height: 23px;
padding: 0;
line-height: 23px;
background-color: #0a2d7f;
}
IE6 stretches the last <li> to the total width of the <ul>'s parent. IE7 doesn't stretch it at all. How do I make it work in these two browsers also?
PS.: Firefox, Chrome and Opera work a expected.
Can ul.grafiek be defined an explicit width? If so that should work out for IE, as it has issues calculating the total width of floats.
Try setting position: relative; and/or zoom: 1; on ul.grafiek
I have tried like mad to get this done in a clean, CSS-only manner, but I ended up coming to roughly the same point as yourself. IE6 calculates the 100% width of the last list-item first, then wraps the parent around it. (And my IE7 isn't working, couldn't test that.)
What I can recommend is that you create classes for all the different quantities of items you expect (up to a maximum of whatever the screen width will accommodate), and modify the class of the UL to match the number of LI's inside (again, up to the same maximum).
So your UL gains one class:
<ul class="grafiek items6_grafiek">
<li class="first-child">item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li>item</li>
<li class="last-child">item</li>
</ul>
And add to your existing CSS:
.items1_grafiek {width: 56px}
.items2_grafiek {width: 118px}
.items3_grafiek {width: 180px}
.items4_grafiek {width: 242px}
.items5_grafiek {width: 304px}
.items6_grafiek {width: 366px}
And possibly, if you are adding items dynamically in JS, you'll need to change the itemsN_grafiek class to the correct one.
I noticed that you have a fixed height on that last element. That opens us up the door to try some absolute positioning tricks, and I think that (along with some CSS hacks or conditional comments) will get you what you're looking for.
If I change ul.grafiek like so:
ul.grafiek {
float: left;
position: relative;
border: 1px dashed gray; /* just for visualization while working on the problem */
margin: 0;
padding: 1px;
*padding-bottom: 33px;
}
And add *position: absolute; and *bottom: 0; to ul.grafiek li.last-child, I get a layout that's essentially the same in Firefox 3.6, Safari 4, IE6, and IE7.
I say essentially because there are some differences in the li heights between IE and everything else. These will go away if you add a doctype declaration, but the layout will then break in IE6 again. :|