I need to create a drop down navigation menu which wraps onto two lines when it is really long.
By setting the following CSS properties on the menu I can achieve the desired result.
.dynamic {
position: absolute;
max-height: 80px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
This, however, does not work on Internet Explorer 11. The items do not wrap onto the next line as it does on Chrome.
Here is a jsFiddle
It will work if I use height: 80px instead of max-height: 80px; but that does not work for me as I want the menu to grow with the items.
Does anyone know how I can get IE to wrap the items properly?
Since CSS Flexbox is not fully supported to provided a wrapping menu when the items pass a maximum height I have created a workaround using the height attribute.
As #Michael_B pointed out, the container doesn't wrap around the wrapped items.
A solution to this is apply the background style to the flex items instead of the container like this
This allows the container 'to appear' to grow with the items. Then using the nth-child pseudos I can allow the last item to span the full height of the container.
.dynamic > li:nth-child(4n),
.dynamic > li:last-child:nth-child(n+4) {
flex: 1 0 auto;
}
Related
Example code:
https://jsfiddle.net/z7ybks9u/2/
Motivation: I would like to force a 3 column layout, WITH support for fixed width but variable height DIVS, wit layout efficiency that will not expose large "whitespace holes" between items. Since the number of elements is unknown, I cannot limit the height of the flex container.
Problem: without forcing the height of the flex container, I cannot see more than one column, as it just utilizes the vertical space it needs to fit all items in one column.
What I am forced to do:
gallery-height {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: center;
max-height: 700px; <----- NEED TO DO THAT TO SEE COLUMNS BUT I HAVE TO SUPPORT UNKNOWN NBR OF ELEMENTS
}
Dropping the Flex container in favor of column-count might help: https://jsfiddle.net/69nmwqag/
.gallery-height {
column-count: 3;
}
Then I dropped width: 30%; on .img.
Can someone let me know if this is an undocumented bug with flexbox, or that I'm just doing it wrong? I've got 3 images lined up in a row inside a div container. This is as simple as it gets folks.
Without any hyperlinks, all 3 images shrink down perfectly as they should.
<div style="width: 100%; margin: 0 auto; display: flex; justify-content: center;">
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
</div>
Now, only 2 out of the 3 images when viewed on all devices shrink down correctly depending on manually maximizing dragging the browser, of via viewport.
The only image that will not change shape or size is the image with the hyperlink. So, I took the hyperlink off the first image. And decided to test it by placing it on the 2nd, now the 1st image and the 3rd image shrinks fine.
But, the 2nd image stays the exact same size? Tried then adding hyperlinks to all the images and none of them change to match the screen width?
Am I wrong to say flex items if they are images won't flex if they have a hyperlink lol? Surely this cannot be the case right?
The problem has nothing to do with hyperlinks. You could wrap the image in any element (try a span or a div) and it will have the same effect as the a container.
The problem is the hierarchical structure of a flex container.
When you set an element to display: flex (or inline-flex) you establish a flex container.
Only the children of a flex container are flex items. Descendants of a flex container beyond the children are not flex items and don't accept flex properties.
Here are the three flex items:
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
The img in the first element is not a flex item. It is wrapped by the a element and is therefore a child of a flex item.
The two img items can shrink because of two default settings on a flex container:
flex-wrap: nowrap ~ flex items are forced to remain on a single line
flex-shrink: 1 ~ flex items are permitted to shrink to prevent them from overflowing the container
If you switch to flex-wrap: wrap and/or flex-shrink: 0 the img items will no longer shrink.
The a item does not shrink because of another default setting: min-width: auto, which means that flex items cannot be smaller than the size of their content. In this case, the a item cannot shrink below the width of the image.
You can override this setting by adding min-width: 0 to your code.
#container {
display: flex;
}
span {
min-width: 0;
display: flex;
}
img {
min-width: 0;
}
<div id="container">
<span><img src="http://i.imgur.com/60PVLis.png"></span>
<img src="http://i.imgur.com/60PVLis.png">
<img src="http://i.imgur.com/60PVLis.png">
</div>
More information:
Why don't flex items shrink past content size?
Proper use of flex properties when nesting flex containers
I don't know why, but this solves the problem. I would like to know why as I cannot find out any information about this issue in any HTML/CSS documents.
If you add the following.
<style>
img {
max-width: 100%;
height: auto;
}
</style>
Then all 3 images will shink perfectly. Even if they have hyperlinks. Funny enough if you set just the width: 100%; then the image with the hyperlink stays the exact same size as the image is, and all the others without hyperlinks blow up to the 100% size of the container.
I didn't know flexbox had such rules that needed you to set image max-widths to make items responsive/shrink down if they have a hyperlink attached.
So, tried it in chrome: Only the image now with the anchor shrinks down, the other 2 stay the same size. FireFox all 3 shrink down, but chrome only shrinks the image with the hyperlink wrapped around it.
Tried wrapping hyperlinks around each of the other 2 images and in chrome, they all shrink down fine.
Can someone explain what is going on? How can i set a max-width: and height: auto on a hyperlink?
It's tough to say without seeing your CSS, but you probably are not selecting the images within <a> tags. If you alter your CSS to select images that are inside of <a> tags, it should work fine.
I've added my complete working solution. Thanks to many people here giving their various methods. So, this is for anyone else who may be struggling.
First lets set the style's up.
<style>
img {
max-width: 100%;
width: 100%;
min-width: 0;
min-height: 0;
}
</style>
adding min-width: 0; | min-height: 0; seems to be overkill, but with chrome, it works much better apparently than setting them as auto;
Since it's using flexbox we don't add the usual width: 33.33%; even if there are 3 images. In flexbox, this will just space them out way to far apart within a 100% wide div.
Here's the really important part I found out the hard way.
You must use either width: 100% on the images, or max-width: 100%; otherwise, (On Chrome without adding either 100% width or max-width: 100%; it just won't flex/shrink down when you minimize the browser to test its responsiveness.)
So, next to keep each of the 3 images in perfect aspect ratio remember to include each image inside its own div container. Otherwise, they will shrink but will just skew up to each other as they do.
As you can see the first image is even wrapped in a hyperlink, but because it's inside its own div it will shrink and grow completely flush and inline with the other images. This saves using extra markup and saves adding a span tag then making that a flex container to contain the hyperlink. I've tried both ways this is by far the easier method.
I've used inline styles for the flexbox container. (bad habit.)
<div style="border: 2px solid red; margin: 0 auto; display: flex; justify-content: center;">
<div>
<img src="flash-tooltip.png">
</div>
<div>
<img src="html-tooltip.png">
</div>
<div>
<img src="portables-tooltip.png">
</div>
</div>
Remember to close off that last /div it's a real gotcha!
And that's how I've done it. Tested it in many browsers works perfectly. Even on mobile phones and tablets.
If you don't like flexbox? You can do the same thing using regular floats.
I've included this same method as above, only this time in a float: version.
So... I got this code: https://jsfiddle.net/jmg63s3e/1/
The code actually works fine if you resize the browser window until you have the text inline with the image and that's what I'm trying to achieve, but if you resize it down eventually the text drops below the image even if the wrapper width is a lot smaller than the window width.
My only purpose is to have:
the whole wrapper centered both vertically and horizontally in the browser window. Its total width and height unknown, depending on its children
row1 and row2 must not be inline: row2 must be below row1
All the elements inside row1 (the image and the text containing 2 spans) must be inline with each other
And well, the spinner inside row2 must also be centered inside the row but that was never a problem whatever solution I tried
As a matter of fact the only dynamic element in the whole code is the first span which in the example contains Player #1, since it should be the name of the player and it can be anything, any length.
Of course if I wanna make it responsive I will have to use media queries or dynamically change widths and heights and font-sizes with JS, and I'm willing to do so. My problem here is only the wrapper itself and the text that drops below the image even if the wrapper width is a lot smaller than the window width, so I'm asking for a solution that works as long as the wrapper width is smaller than the window width. When the wrapper width drops below the window width, I will handle the style with responsive media queries or JS. I would just like to have the wrapper to be centered both vertically and horizontally in the window, and its size to be dynamic and depending on children.
I've already tried any solution I could think of, but with an unknown wrapper width I just can't figure it out. Can someone help me please? I'm open to any suggestion and any solution, as long as it's pure CSS and it doesn't involve JS. Thanks everyone in advance
You can use flexbox to fix these problems.
Here's an updated fiddle with old CSS commented out: https://jsfiddle.net/jmg63s3e/3/
First, to align the wrapper both horizontally and vertically you need to make the parent container a flex container with display: flex and use justify-content: center and align-items: center. You also need to set a height or else it will wrap to the height of the child and not give you the centering effect. I used the following. The height can be whatever you need it to be.
.trump-waiting {
display: flex;
justify-content: center;
align-items: center;
font-size: 0;
overflow: hidden;
height: 100vh;
}
Next, I used display: flex on the wrapper and flex-direction: column to make sure they are all lined up like we want them to be.
.trump-waiting .wrapper {
display:flex;
flex-direction:column;
To fix row1, again I used flexbox and removed the inline-block and the set height. You could set the height as long as you take care of resizing the font in the text divs, with media queries for instance. Otherwise, with an explicit height, the font at the size it's at now will break out of their containers. Without explicitly setting the height, the containers will adjust in size.
.trump-waiting .row1 {
display: flex;
flex-direction: row;
/* display: inline-block; */
/* height: 60px; */
background-color: yellow;
}
I also added flex-shrink:0 to .image to keep it from shrinking on resize.
To keep Player #1 and 'is choosing the trump suit' inline, I also added display: flex and flex-direction: row to .row keep them on the same line.
Finally, to align the loader, I did the vertical/horizontal alignment trick used above, plus added some padding to the div to give it some space and removed the old css.
.trump-waiting .row2 {
display: flex;
justify-content: center;
align-items: center;
padding: 16px 0 16px 0;
/* display: block; */
/* margin-top: 50px; */
The last step would be to use media queries to adjust the font-sizes on .text spans so the font doesn't expand their container on resize.
Many ways to skin a cat and I'm sure others will have different perhaps better solutions, but hope this helps. There's a great summary of flexbox here if you need it. I may have left out a change in this summary, but it should all be in the fiddle.
EDIT: Realized I made a mistake summarizing the css in the jsfiddle and also removed a redundant css property. Now updated.
This question already has answers here:
Absolutely positioned flex item is not removed from the normal flow in IE11
(4 answers)
Closed 6 years ago.
I'm currently trying to build a responsive website layout with flexbox.
Depending on the screen size I want an element to have position: fixed; This itself is working. But when I use justify-content: space-between; on a column that contains an element that gets moved out of the of column itself with position: fixed; the space distribution uses this element as an 0 height element.
For the sake of demonstration I set up two examples. Both do not use media queries because they are not the problem.
In the first example I created what I want the final result to look like. I had to move #fixed outside of .column in order for the space distribution to work properly.
In the second example I created the desired HTML markup. When you compare both example side by side you will notice that the spacing looks odd in the second. The browser is not making an error here because there is an element it has to respect when distributing the space. I (in a nutshell) would like the browser to pretend #fixed is not inside the container and therefore not consider it when distributing space.
This is how the result should look: https://jsfiddle.net/5nu9nsyL/3/
And this is how the html should look: https://jsfiddle.net/5nu9nsyL/4/
(Only Chrome and Safari renders it correctly. So if both look the same to you have a look at it with a different browser like Firefox or IE)
I hope I made my it clear what I want.
(Note I must use display: flex on the container .column)
(I also need a JavaScript free, CSS only solution)
This is Firefox bug 874718. The spec says
The justify-content property aligns flex items along the
main axis of the current line of the flex container.
Since an absolutely (including fixedly) positioned element is out-of-flow, is not a flex item (this is fully defined in Absolutely-Positioned Flex Children). So justify-content should ignore it.
But Firefox wraps it inside an anonymous flex item, according to an old spec:
Absolutely positioned children of a flex container are not themselves
flex items, but they leave behind "placeholders" in their normal
position in the box tree. These placeholders are anonymous inline
boxes with a width, height, and line-height of ‘0’, and they interact
normally with the flexbox layout algorithm. In particular, they'll
trigger the creation of anonymous flex items, or join neighboring
inline elements in their anonymous flex items.
To fix that, instead of using justify-content, I recommend aligning with auto margins:
.column > div:not(:first-child) {
margin-top: auto;
}
That will distribute free space equally before the children of the flex container, except the first one. The effect should be like justify-content: space-between.
In the case of the fixed element, that auto margin will just compute to 0.
.column {
display: flex;
flex-flow: column nowrap;
height: 300px;
float: left;
margin: 10px;
border: 3px solid black;
}
.column > div:not(:first-child) {
margin-top: auto;
}
.column > div,
#fixed {
display: flex;
justify-content: center;
align-items: center;
width: 200px;
height: 50px;
background-color: red;
}
#fixed {
position: fixed;
top: 0;
right: 0;
}
<div class="column">
<div>Element 1</div>
<div id="fixed">Element 2</div>
<div>Element 3</div>
<div>Element 4</div>
<div>Element 5</div>
</div>
Update
Upon reviewing the OP once more, this is the objective:
When the screen width is at a certain size (I determined 720px+), #fixed(col2 ele2) is position: fixed, if it's at a smaller width, it will be position: static. When #fixed is "fixed" it is no longer in col2, therefore the spacing between col2's children increase. What is desired is a consistent spacing between all divs (ie col2 spacing must coincide with col1 spacing).
The OP did not provide a means to show both states: fixed and static; of which static needed to be established. I have added two media queries that will insure both static and fixed states of #fixed will be triggered at 720px.
#media screen and (min-width: 721px) {
.spacer {
display: none;
}
#fixed {
position: fixed;
}
.column.column {
justify-content: space-between !important;
}
}
#media screen and (max-width: 720px) {
.spacer.spacer {
display: none !important;
}
#fixed {
position: static;
}
.column.column {
justify-content: space-between !important;
}
}
For some reason, when applying just the properties display and position, the justify-content: space-between would break. So I included justify-content: space-between to both media queries, unfortunately that didn't work either. So then I added !important, and it still failed. So then I used my secret ninja technique and doubled the class selector .column.column and I was victorious! Doubling up on a selector will increase it's specitivity to trump anything.
Plunker in Full Screen Mode Resize the browser to see the magic.
Plunker in Preview Mode
I don't understand what you want to with #fixed. But I do understand the problem described in the demo:
The space between Element 1 and Element 3 in the second column should be the same height as the other spaces.
Since the second column cannot arbitrarily space it's content by a predetermined length due to the nature of justify-content: space-between, you'll need just as many divs as the first column in order to obtain the same spacing as the first column. As I understand it, you cannot hard code layout (HTML), so I wrote a little JS to create an invisible div and append it to the second column thereby making the space between element 1 and 3 the same as the spaces between the children of the first column.
Fiddle
I have a container that holds an image. The image fills the container horizontally and the container responds to page size. See fiddle:
im html
<div id="container">
<img src="http://silberschauer.de/img/pre/045.jpg" />
</div>
in css
#container {position:absolute;top:1em;left:1em;bottom:2em;
width:30%;background:#0f0;overflow:hidden;}
#container img {width:100%;}
https://jsfiddle.net/t4um60k1/8/
Is it possible to have the image clip top and bottom equally if (and just if) the container gets smaller in y-axis than the image with css?
EDIT:
You did not understand the question if your solution provides a green area ABOVE the image in any circumstances.
Is it possible to have the image clip top and bottom equally while staying top-aligned if the container gets smaller in v-axis than the image with css?
Yes, this can be done neatly and efficiently with CSS. Flexbox is well-suited for this sort of thing.
No need for JS. No changes to the HTML.
Add this to your CSS:
#container {
display: flex; /* new */
flex-direction: column; /* new */
justify-content: space-between; /* new */
position: absolute;
top: 1em;
left: 1em;
bottom: 2em;
width: 30%;
background: #0f0;
overflow: hidden;
}
#container::before, #container::after {
content: '';
}
#container img {
width: 100%;
flex-shrink: 0;
}
https://jsfiddle.net/t4um60k1/10/
Explanation
We use flexbox to align the image on a vertical axis (flex-direction: column).
Then we tell the flex container that any child elements (aka, flex items) will align as space-between.
With justify-content: space-between, flex items are evenly spaced, with the first item aligned at one edge of the container and the last item aligned at the opposite edge. In this case, because we're in column direction, we're talking about the top and bottom edges.
To ensure that the image stays in the middle, we create "phantom" flex items on each end using pseudo-elements.
But why take these extra steps to center the image, when justify-content: center would have done the job with less hassle?
Because the second requirement of the question is that the image must be top-aligned when it exceeds the height of the container.
With justify-content: center the image will stay centered at all times.
But under the rules of space-between, if flex items overflow the container, space-between switches to flex-start, which aligns the image to the top (more details below).
Lastly, as flex items are generally flexible, flex-shrink: 0 is applied to the image to ensure it doesn't shrink from its original size.
Switching from space-between to flex-start
From the spec:
space-between
Flex items are evenly distributed in the line. If the leftover
free-space is negative or there is only a single flex item on the
line, this value is identical to flex-start.
center
Flex items are packed toward the center of the line. ... If the leftover
free-space is negative, the flex items will overflow equally in both
directions.
(emphasis mine)
source: https://www.w3.org/TR/css-flexbox-1/#justify-content-property
Note that flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. For a quick way to add all the prefixes you need, post your CSS in the left panel here: Autoprefixer.
You can simply add some css tricks to your image. It's not the modern way, but it works.
#container img {
width:100%;
position: absolute;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
jsfiddle
When the container gets smaller than the image in v-axis, the image is align-top.