Stacking divs from the bottom right - css

I am adding colour blocks (divs with bg colours) to a parent div. Each parent div can have a number of these colour blocks which are to display in the bottom right of the parent, with a maximum of three to a row.
My code (below) does what is required for 3 or less colours, but if a forth colour is added it jumps to the line below leaving two empty spaces on the bottom line. What I would like to happen is for the forth colour to be displayed on the line above so the bottom line has no blanks.
You can see the problem in action here along with a hardcoded example of what I would like to happen.
<style>
.container {
position: relative;
width: 200px;
height: 142px;
}
.colorSwatches {
position: absolute;
bottom: 0px;
right: 0px;
max-width: 100px;
max-height:60px;
text-align:right
}
.swatch {
display: inline-block;
width: 25px;
margin: 2px;
height: 25px;
background-color: rgb(255, 0, 0); ///or whatever
}
</style>
<div class="container">
<div class="colorSwatches">
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
</div>
</div>
Thanks for any help.

I think you can pull off that layout with some flexbox magic:
set your .swatches container, in your case .colorSwatches, with display: flex prop
then to this container and a flex-wrap rule of: flex-wrap: wrap-reverse, so that the children inside it will wrap, on to the next line, in opposite direction of the flex-direction, which by default is row I think.
and lastly, add to the container, the justify-content: flex-end; so that the items inside will start laying out at the end of their container.
Here's a jsfiddle demo and a couple of resources:
Flexbox
Justify-content
Flex-wrap

Related

Center text above wrapped, fixed-width items, ignoring container's leftover space

We want the layout that's shown below but don't know how to center the "Center here" text like that. Currently, we're centering it according to the width of the parent container. It's appearing too far to the right. In this example, only two items fit on a row, thus leaving empty space to the right of the items. We want the parent container's width to be as per the min width of the child flexbox to center the text above it. The flex box is flex row with wrapping for items that don't fit in. We basically want to ignore that extra space on the right where the item can't fit and set the width of the parent div accordingly
The blue color represents the flex-box's width. Here's the tailwind CSS classes that we're currently using:
className="flex flex-row overflow-x-hidden flex-wrap 3xl:flex-shrink 2xl:block 2xl:grid 2xl:grid-cols-3 3xl:grid-cols-3 justify-items-end "
Hard no sample code, but here I tried my best, hope it helps
This is my code sample, you can try it :
body{
padding: 5%;
}
.container{
border: 5px solid #000;
width: 300px;
height: 400px;
}
.container-box{
margin: auto;
display: flex;
flex-wrap: nowrap;
padding: 10px;
width: 200px;
height: 200px;
}
.box-1, .box-2{
margin: auto;
border: 5px solid #000;
width: 40%;
height: 40%;
}
<div class="container">
<div class="container-box">
<div class="box-1"></div>
<div class="box-2"></div>
</div>
</div>

How set full screen width background on fixed width element?

I have simple structure of element container of dynamic height and fixed width (Markup below). On one hand the element's background should span the whole window width, on the other the children's size must be limited by the container (Desired layout below). The number of children and their sizes (which are equal on the image only for simplicity) are dynamic.
Is that possible without adding extra container? I want to avoid achieving the desired element content width by setting width on the children, because their number is dynamic and the size relationships become complicated to write unless their total width is already limited by container's width.
Here's a pen to experiment;
Markup
<div class="container">
<div class="child">
<div class="child">
...
</div>
.container {
width: <fixed-width>px;
}
Desired layout (the whitespace between children and container is irrelevant)
One route we can take to solve this is by using viewport width on the parent container padding, to force the children into a box that is only 500px wide (as per your codepen).
The important thing to remember when doing this is that box-sizing:border-box; will need to be set on the container, otherwise the padding goes ballistic.
We do this by using calc, vw and padding.
padding: 20px calc(50vw - /*half of container width*/);
Here's the full expanded code of your container on the linked codepen:
.container {
display: flex;
flex-flow: row nowrap;
justify-content: center;
margin-left: auto;
margin-right: auto;
height: 300px;
width: 100%;
padding: 20px calc(50vw - 250px);
background-color: #acffac;
background-size: 100vw auto;
background-position: center top;
box-sizing: border-box;
}
html {
overflow-y:scroll; /* fixes potential calculation errors caused by scroll bar - thanks to Roberts comment */
}
Here's a working version of the codepen, and for the sake of keeping all my eggs in one basket, here's an expandable code snippet:
.container {
display: flex;
flex-flow: row nowrap;
justify-content: center;
margin-left: auto;
margin-right: auto;
height: 300px;
width: 100%;
padding: 20px calc(50vw - 250px);
background-color: #acffac;
background-size: 100vw auto;
background-position: center top;
box-sizing: border-box;
}
.child {
flex: 1 0 auto;
width: 100px;
height: 100%;
background-color: #ff4444;
}
.child+.child {
margin-left: 20px;
}
<div class="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
I will finish off by pointing out that if someone else has a better solution, you may want to look at that for time being instead as there is some issues with using vw inside calc on older versions of Chrome and Safari.
EDIT:
As noted in the comments by Vadim and Robert there are a few things that can cause some snags.
Firstly, assuming you are working with a bare minimum template (i.e. no normalize/reset.css), your body will most probably still have the inherent margins that would mess with this kind of layout. You can fix this with:
body {
margin:0;
}
Secondly, depending on your OS (Yes I'm looking at you Microsoft!) your scrollbars can push your content to the side whilst simultaneously still being included in the calculation for vw.
We can fix this one of two way. The first being an adjustment on the padding calculation to include the scrollbar side, but you would have to write a script to ensure that scrollbar is actually present, and scrollbars differ in sizes (I.E -> 17px, Edge -> 12px).
The other alternative would be to use a custom content scroller, which would do a full overflow:hidden; over the content, thereby removing the scroll bar, before implementing it's own version of a scrollbar (which generally lies on top of the content with a position:fixed;) it.
Using vw and flex we can center the child elements and achieve exactly what you require. I have written a JSfiddle where you can check it out.
Basically what I have done is created a container with display set to flex. Using margin property of the first child element, I have centered all of the other child divs and then the regular properties were added to other divs.
Here's the code
body{
margin: 0;
padding: 0;
}
#container{
display: flex;
width: 100vw;
height: 40vw;
background-color: #333333;
align-items: center;
}
.child{
width: 4vw;
height: 80%;
background-color: red;
margin-right: 10vw;
}
.child:first-child{
margin-left: 28vw;
}
<div id="container">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

How do I make proper vertical margin between 2 inline blocks?

I have two divs with display:inline block next to each other, however the 2nd one's width can change to be so long that it will fall under the first div. That is fine, but the problem is that there is no vertical space between the 2 divs when this happens. I can solve this by adding margin-bottom to the first div, but then this causes the 2nd div to be a bit lower even when it is sitting to the right of the first div.
What browser are you using? As you can see below, two inline-block divs retain a margin when one slips below the other. (In fact, getting rid of the margin between inline-block elements is a bit tricky, but that's another question.)
#container {
width: 200px;
}
#top {
display: inline-block;
width: 100px;
height: 100px;
background: red;
}
#right {
display: inline-block;
width: 150px;
height: 100px;
background: blue;
}
<div id="container">
<div id="top"></div><div id="right"></div>
</div>
What you want is "vertical-align:top;".

Align flex-box items to baseline of last text line in a block

I am trying to achive the last example on the following image, using flex-box.
From what I see, the align-items: baseline; property works great when the blocks only have 1 line.
The property align-items: flex-end; creates some issues mainly because the left and right items have different font-sizes and line-heights. Although the edges of the items are aligned, the white space created by the font size and line-height differences looks really bad when the item has no borders.
I'm trying to find a good all-around solution without any JS.
Thanks in advance.
You can wrap the contents of the flex items inside inline-block wrappers:
.flex {
display: flex;
align-items: baseline;
}
.inline-block {
display: inline-block;
}
.item { border: 1px solid red; }
.item:first-child { font-size: 200%; }
.flex::after { content: ''; position: absolute; left: 0; right: 0; border-top: 1px solid blue; }
<div class="flex">
<div class="item">
<div class="inline-block">Lorem<br />Ipsum<br />Dolor</div>
</div>
<div class="item">
<div class="inline-block">Foo bar</div>
</div>
</div>
That will work because, according to CSS 2.1,
The baseline of an 'inline-block' is the baseline of its last line box
in the normal flow, unless it has either no in-flow line
boxes or if its 'overflow' property has a computed value other than
'visible', in which case the baseline is the bottom margin
edge.
At the time of writing the CSS box model alignment working draft proposes a ‘first’ and ‘last’ value to be added to ‘align-items’. The would allow:
align-items: last baseline
Current it only appears to be supported by Firefox so is one for the future.
https://developer.mozilla.org/en-US/docs/Web/CSS/align-items

Two divs with fixed widths need equidistant spacing in a parent div

I have two divs (which have a fixed width of 150px) within another parent div, which has a changing width, depending on the browser width.
I would like to position the two child divs within the parent, so the margin between the two divs would be equal to the margins between the edges of the parent div and child divs.
Example with red arrows always having equal lenghts:
edit: you could do what I first suggested, but now add
#leftwrapper, #rightwrapper { text-align: center; }
#childdiv1, #childdiv2 { display: inline-block; }
inline-block, instead of block, and you don't need the margins then for child div...
if that don't work, which probably won't, it might be VERY hard to get what you want to happen without using a table
you would have to create two new div wrappers
so you have
#parentdiv { display: block; width: 100%; }
#leftwrapper { display: inline-block; width: 50%; }
#rightwrapper { display: inline-block; width: 50%; }
#childdiv1 { display: block; margin: 0 auto; }
#childdiv2 { display: block; margin: 0 auto; }
html would be like
<div id="parentdiv">
<div id="leftwrapper">
<div id="childdiv1">your stuff</div>
</div>
<div id="rightwrapper">
<div id="childdiv2">your stuff</div>
</div>
</div>

Resources