I have a set of images that I want to display in the following pattern:
[1] [4] [7] [10] [13]
[2] [5] [8] [11] ...
[3] [6] [9] [12]
I know that I can always manually group 3 images into a div.column or something similar, but I want to achieve this layout with as simple HTML as possible. The images are 225x150.
Currently, I have the following HTML:
<div class='album'>
<img src='img/01.jpg' />
<img src='img/01.jpg' />
...
</div>
And here's my stylesheet:
.album {
background: #faa;
display: block;
-webkit-column-count:2;
-webkit-column-gap: 10px;
height: 450px;
width: 460px;
}
.album img {
display: block;
width: 100%;
}
Chapter 8.2 in the specs describes that if I specify a height and the content won't fit in, more columns are created as needed, which is basically just what I want.
As you can see, I specified a background color for the .album. This does only cover the first two columns though, since I set the width to 460px. However, I really need an element that has the exact size/width of the album's content, i.e. an element wrapping the album with that exact size.
None of the possibilities I tried seemed to work tho. (100%, auto, played with overflow as well)
Does anyone have an idea on how I could create such a wrapper element for my albums?
You may be stuck using Flexbox for this purpose, since using columns within inline elements (inline-block, etc.) causes some browsers to miscalculate the width of the element.
http://codepen.io/cimmanon/pen/vuxjF
.album {
background: #faa;
height: 480px;
padding: 5px;
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
-webkit-flex-flow: column wrap;
-ms-flex-flow: column wrap;
flex-flow: column wrap;
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}
#supports (flex-wrap: wrap) {
.album {
display: inline-flex;
}
}
.album img {
margin: 5px;
}
Similary thing was asked also at With column-count, can you dynamically change from 3 to 2 columns if resolution smaller?. CSS columns answered there might be good to check? (columns is a shorthad for column-width + column-count, see the spec & codepen demo).
Note that browser support varies & -moz/-webkit prefixes are needed currently (http://caniuse.com/#search=column).
Related
I have two divs inside a flex box. Div A is on the left, and div B is on the right.
I would like div A to take up 60% of the flex box, and div B to take up 40% of the flex box. As you can imagine, my css will look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
}
Also, the browser will look like this:
Now, I would like div B to have a maximum and minimum width, the code will now look like this:
.container {
display: flex;
justify-content: start;
flex-direction: column;
}
.div_a {
width: 60%;
}
.div_b {
width: 40%;
max-width: 768px;
min-width: 480px;
}
Unfortunately, this will lead to this situation large browsers.
When Div B has reached its maximum width, I would like div A to fill up the rest of the space, like this:
Any ideas or fixes would be appreciated, thank you very much in advance.
I should mention that min-width: 60% for Div A produces the same situation, unfortunately.
This is a perfect case where you would turn towards the property flex-grow.
Since you're working with a 60%/40% size, you can use flex-grow:6 and flex-grow:4, or alternatively: flex-grow:3 and flex-grow:2. Or even: flex-grow:1.5 and flex-grow:1 since the property also accepts decimals!
.div_a {
flex-grow:3;
}
.div_b {
flex-grow: 2;
max-width: 768px;
min-width: 480px;
}
flex-grow is a property that will tell the parent (flexbox) to divide the available width into whatever the sum is of the amount of flex-grow specified in its child elements. By limiting the max width of .div_b, you tell flexbox to stop increasing the width after it reached that max, and the remaining width will be reserved for the other elements (.div_a in this case).
Also
I do want to point out that you're using flex-direction:column, but you're trying to create a row based layout. It's a better idea to use flex-flow: row nowrap. Which is a shorthand to declare both flex-direction and flex-wrap together and, with the value row nowrap will tell the parent to force everything on one line in a horizontal layout.
.container {
display: flex;
justify-content: start;
// flex-direction: column;
flex-flow: row nowrap;
}
I am using CSS Grid to display some tags. If a tag is large (ie. it's width is more than 150px), I would like that item to span into more columns as needed. For example, in the image I would like the red tag to span into two columns so that the text remains in one line.
Is it possible to do something like that without adding a specific class to the target element? I am mapping through an array in React to generate each of these divs so it won't be possible to add a class to that element only.
index.js
<div className={styles.container}>
<>
{tags.map(tag => {
return <TagBlock tag={tag} />
})}
</>
</div>
style.css
.container {
margin: 30px auto;
width: 90%;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, auto));
grid-gap: 20px;
}
Don't know a way to implement a gradual column width increase via CSS only. A JS logic will be required to set "how many columns it should take". Then one of the following cases.
explicitly style for the "wide" column:
grid-column: span X;
where X is how many columns should take your element.
Set predefined classes (like at Bootstrap: col-1, col-2), then apply them.
If a column could have any width, then I would recommend you to use a flexbox with wrapping. Kind of:
.container {
margin: 30px auto;
width: 90%;
/*added properties below*/
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
/*TagBlock base style that grid generated on its own*/
TagBlock {
margin: 25px;
min-height: 120px;
min-width: 120px;
}
Hope, this will help a little.
Centred flexbox items can have undesirable behaviour when they overflow their container.
Several non-flex solutions have been provided for this issue, but according to MDN there is a safe value which is described as follows.
If the size of the item overflows the alignment container, the item is instead aligned as if the alignment mode were start.
It can be used as follows.
align-items: safe center;
Unfortunately, I haven't been able to find any examples or discussions of this, or determine how much browser support there is for it.
I have attempted to use safe in this CodePen. However, it doesn't work for me. The safe seems to be ignored, or perhaps the container element is improperly styled.
I'd really appreciate it if anyone could shed some light on safe and whether and how it can be used to solve the overflow problem, as demonstrated by the CodePen example.
The newer keyword safe still has bad browser support, so to get the same effect, cross browser, use auto margins for now, which should be set on the flex item.
Updated codepen
Note, to compensate for the modal's 50px top/bottom margin, use padding on modal-container.
.modal-container
{
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start; /* changed */
position: fixed;
width: 100vw;
height: 100vh;
overflow-y: scroll;
padding: 50px 0; /* added */
box-sizing: border-box; /* added */
}
.modal-container > #modal
{
display: flex;
flex-direction: column;
align-items: center;
margin: auto 0; /* changed */
padding: 12px;
width: 50%;
background-color: #333;
cursor: pointer;
}
safe isn't implemented in most browsers yet. You can recreate some of its functionality with auto margins.
I was trying to use justify-content: safe center to have a bunch of items centered in a footer when the viewport was wide, but have them able to scroll without clipping off the left side when the viewport was small.
When I tried to fix this with auto margins as Ason suggested, it did fix the clipping, but it also spread the items out evenly, which isn't what I wanted.
I found I could simulate safe center in this context by applying auto margins to only the first and last elements.
Assuming my flex items have class "item":
.item:first-child {
margin-left: auto;
}
.item:last-child {
margin-right: auto;
}
CodePen with examples comparing each solution
Use align-items: flex-start; instead of using it with the safe keyword, Also, you can add margin/padding to get the desired behavior for the same.
I am using a flexbox layout that is usually presented as a row but when the screen is a certain width it switches to column. This works fine in Chrome, Firefox, Safari and Edge but on IE 11 the flex elements will not center even though I am using justify-content: space-around;
I have looked at https://github.com/philipwalton/flexbugs and other websites that list flexbox bugs and I can't seem to find the solution.
I have distilled it down to a simple example to demonstrate the problem.
First we have a container that spans the width of the screen with the following properties:
.container {
display: flex;
flex-direction: column;
justify-content: space-around;
text-align: center;
width: 100%;
}
Then inside it we have four cells with the following properties:
.cell {
flex-grow: 2;
text-align: center;
display: inline-block;
background-color: green;
margin: 5px auto;
min-width: 50px;
max-width: 20%;
}
On IE the four cells are aligned left, but on any of the other browsers the cells are center aligned.
Here is an artist's impression of the situation
I have created a JSFiddle that demonstrates the issue at https://jsfiddle.net/8w1gf7vx/4/
You are using the wrong property - justify-content is for alignment on the main axis. Your flex-direction is column, therefor the main axis goes from top to bottom - and so all justify-content does here is influence the distribution of space above and below your items.
You want to align your items on the cross axis - and the property to achieve that is align-items.
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
https://jsfiddle.net/8w1gf7vx/6/
text-align: center; and display:inline-block from the items can be removed - unless you want to use those as a fallback for browsers that don't understand flexbox. (I suspect they might be the reason that what you had seemed to work as intended in other browsers. As Oriol pointed out in comment, that's rather due to margin-left/-right being auto - and that IE doesn't seem to support that.)
http://flexboxfroggy.com/ is a nice way to get a better understanding of what the different flex properties do, in the form of a little game - might be worth a look for anyone who still struggles a bit with flexbox now and then (and that includes myself ;-)
Disclaimer: I am not affiliated with that site in any way, I just think it is quite useful in gaining a better understanding of flexbox.
Using the following HTML and CSS3 rules, I'm trying to make sure that the following criteria are adhered to:
I have all of the criteria working except for item 1 where the
children are exceeding their parent's width. Question: How to keep children within their parent?
li items cannot exceed their parent width i.e. 400px
img, label, and currency content must be centred vertically within their span
currency should not wrap and should always be displayed in full
currency should always be displayed as close as possible to the
label span.
the label text should be clamped at 2 lines with ellipsis displayed where it exceeds 2 lines.
Note: Only needs to work in Chrome and Safari webkit-based browsers.
It should look like:
However, it looks like this at the moment:
Any ideas?
********************* JS Fiddle example ************************
<ul>
<li>
<span class="img"></span>
<span class="label">Acclaim</span>
<span class="currency">(USD 50)</span>
</li>
<li>
<span class="img"></span>
<span class="label">Acclaim 1 11 111 1111 11111</span>
<span class="currency">(USD 50)</span>
</li>
<li>
<span class="img"></span>
<span class="label">Acclaim 1 11 111 1111 11111 2 22222 2222 22222 3 33 333 3333 33333 4 44 444 4444 44444 5 55 555 5555 55555 6 66 666 6666 66666</span>
<span class="currency">(USD 50)</span>
</li>
</ul>
ul {
width: 400px;
background-color: yellow;
padding: 0;
margin: 0;
}
li {
display: -webkit-box;
padding-right: 50px;
}
.label {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
-webkit-line-clamp: 2;
text-overflow: ellipsis;
overflow: hidden;
white-space: normal;
word-wrap: break-word;
line-height: 1.3em;
margin-right: 0.2em;
background-color: pink;
}
.currency {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-box-pack: center;
white-space: nowrap;
background-color: lightgreen;
}
.img {
display: block;
width: 40px;
height: 40px;
margin-right: 0.1em;
background-image:url('data:image/png;base64,iVBOR...);
}
The following will work, providing the price doesn't get wider:
http://jsfiddle.net/WDjZ3/4/
I simply converted the margin-right to pixels so I knew the space taken up by the content other than the label, then added a max-width for the remainder:
.label {
margin-right: 3px;
max-width: 294px;
}
if the price or image are variable width, you will need js to read their widths, remove from 400px and add that value to max-width.
Here is an example using JavaScript to dynamically set the max-width: http://jsfiddle.net/WDjZ3/7/
I haven't checked all dimensions, so that should be added to make it fully accurate, otherwise the margins will make the price no longer fit.
I basically checked the width of the other elements:
function getWidth(el) {
return parseInt(window.getComputedStyle(el,null).getPropertyValue("width"));
}
I then removed this width from 400px, and set the maxWidth:
for (var i=0; i<imgs.length; i++) {
var width = 400 - (getWidth(imgs[i]) + getWidth(currencies[i])) + "px";
labels[i].style.maxWidth = width;
}
I’ve solved this to work without JavaScript. However, it only works in more modern browsers, including Chrome and Opera. It will not work in Safari. It will work in Firefox once it updates to the latest spec. I can probably get it to work in IE10, but I have to look into that more. The ellipsis only works in Chrome/Safari as it is vendor specific.
The demo is at http://jsfiddle.net/uLm92/1/
First of all we want to make the li as a flexbox container and set it to 400px, so the flex items will try to fit that size (more on that later):
li {
/* make all items inside li as flex items */
display: -webkit-flex;
display: flex;
height: 40px;
max-width: 400px;
}
Now the child items are flex items, the key to getting the label to fit is setting the image and the price to not flex. For the price, we know it wants to always be 40xp wide, so I set the following:
.img {
width: 40px;
height: 40px;
-webkit-flex-basis: 40px;
flex-basis: 40px;
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
This says that the preferred with id 40px and never make it smaller.
Then we want to also tell the price to never shrink, and to also centre the anonymous box (the content):
.currency {
/* make anonymous box vertically centred */
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
/* make sure it never shrinks */
-webkit-flex-shrink: 0;
flex-shrink: 0;
}
Lastly, we want to also center the label text. As you need the ellipsis hack, I've used the old Flexbox syntax for WebKit. Without using old flexbox, the line-clamp property does not work:
.label {
/* need to use old flexbox for line-clamp to work
it is a *horrible hack* */
display: -webkit-box;
display: flex;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow : hidden;
text-overflow: ellipsis;
-webkit-box-pack: center;
align-items: center;
}
As the other two items will never shrink, the .label element is the only one that can, so it reduces in size if there is no space left.