I want to make a div which includes my experience.
So I tried making a div (wrapper) which includes span for each word. Then I tried on each element with nth-child to give a style justify-content: flex-end;
The element goes to the end indeed, but the next element does not take it place. So if I try to flex-end the 'verkoopmedewerker' it goes to the right but a break appears at its previous place so 'plaats' will have a gap between 'functie' and itself.
How can I achieve what the picture shows?
See my DEMO here
.baan {
display: flex;
flex-flow: column;
background: red;
width: 40%;
}
.baan :nth-child(3) {
align-self: flex-end;
}
<h3>Bijbaan</h3>
<div class="baan">
<strong>Lidl</strong>
<span>Functie</span>
<span class="rechts">Verkoopmedewerker</span>
<span>Plaats</span>
<span class="rechts">Almeloplein 73
2533 AD, Den Haag
Part-time, 54 uur P. week
</span>
</div>
This is a possible flexbox solution:
.baan {
display: flex;
flex-flow: row wrap;
background: red;
width: 40%;
}
.baan span{
flex: 1 1 50%; /*change width if you don't want the same width for every "span"*/
}
.baan strong{
flex: 1 1 100%;
}
.baan .rechts{
text-align:right;
}
However, I think CSS-grid is better in your case 'cause works in 2 directions: rows and columns. Flexbox works well only in one direction and you have "to hack" this limit if you want it works like grid.
Related
I have three elements I'm trying to align in my layout.
First, I have a div for feedback, and then a search input, and then a div element for suggestions.
I want the first and last element to have a width of 20%, and the search input to have a width of 60%. Using Flexbox I achieve what I want.
But there's a feature that grows all the divs to the highest element. This means that when search results pop up, the feedback and suggestion elements grow in height with the search div resulting in a messed up layout.
Is there a trick to not grow the divs with the highest element? Just make the divs (#feedback and #suggestions) have the height of the content in them?
#container_add_movies {
display: flex;
}
#container_add_movies #feedback {
width: 20%;
background-color: green;
}
#container_add_movies #search {
width: 60%;
background-color: red;
}
#container_add_movies #suggestions {
width: 20%;
background-color: yellow;
}
<div id='container_add_movies'>
<div id='feedback'>
Feedback
</div>
<div id='search'>
Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>Search
<br>
</div>
<div id='suggestions'>
Suggestions
</div>
</div>
http://codepen.io/alucardu/pen/PPjRzY
You're encountering the flex equal height columns feature.
An initial setting of a flex container is align-items: stretch.
This means that flex items automatically expand the full length of the cross axis of the container. In a row-direction container, the cross axis is vertical (height).
The tallest item sets the height for all siblings. As the tallest item expands, its siblings follow along. Hence, equal height for all items.
To override this default setting, add align-items: flex-start to the flex container:
#container_add_movies {
display: flex;
align-items: flex-start;
}
#container_add_movies {
display: flex;
align-items: flex-start; /* NEW */
}
#container_add_movies #feedback {
width: 20%;
background-color: green;
display: block;
}
#container_add_movies #search {
width: 60%;
background-color: red;
}
#container_add_movies #suggestions {
width: 20%;
background-color: yellow;
}
<div id='container_add_movies'>
<div id='feedback'>Feedback</div>
<div id='search'>
Search<br>Search<br>Search<br>Search<br>Search<br> Search
<br>Search<br>Search<br>Search<br>Search<br>
</div>
<div id='suggestions'>Suggestions</div>
</div>
... or align-self: flex-start to the flex items:
#feedback {
align-self: flex-start;
width: 20%;
background-color: green;
}
#suggestions {
align-self: flex-start;
width: 20%;
background-color: yellow;
}
#container_add_movies {
display: flex;
}
#container_add_movies #search {
width: 60%;
background-color: red;
}
#feedback {
align-self: flex-start; /* NEW */
width: 20%;
background-color: green;
}
#suggestions {
align-self: flex-start; /* NEW */
width: 20%;
background-color: yellow;
}
<div id='container_add_movies'>
<div id='feedback'>Feedback</div>
<div id='search'>
Search<br>Search<br>Search<br>Search<br>Search<br> Search
<br>Search<br>Search<br>Search<br>Search<br>
</div>
<div id='suggestions'>Suggestions</div>
</div>
align-items sets the default value of align-self. With align-self you can override the default on individual items.
More details in the spec:
8.3. Cross-axis Alignment: the align-items and align-self
properties
Flex items can be aligned in the cross axis of the current line of the
flex container, similar to justify-content but in the perpendicular
direction.
align-items sets the default alignment for all of the flex
container’s items, including anonymous flex items.
align-self allows this default alignment to be overridden for
individual flex items.
A bit of history
Since the beginnings of CSS, there have been two layout challenges that have regularly frustrated, perplexed, and annoyed front-end developers:
How to center things, especially vertically, and
How to create equal height columns (tables aside)
Today, with the advent of flexbox, these problems are over.
Centering things has never been easier:
#container {
display: flex;
justify-content: center; /* center flex items along the main axis */
align-items: center; /* center flex items along the cross axis */
}
Simple. Easy. Efficient. The craziness is over.
In terms of equal height columns, flexbox also excels: It does this by default.
#container {
display: flex;
flex-direction: row; /* not even necessary; default rule */
align-items: stretch; /* not even necessary; default rule */
}
The align-items: stretch rule tells flex items to expand along the cross-axis as much as possible. Hence, in a row-direction container all items can be equal height. More craziness tamed by flexbox.
From one popular answer for equal height columns:
Give overflow: hidden to the container and large (and equal)
negative margin and positive padding to columns. Note that this
method has some problems, e.g. anchor links won't work within your
layout.
Now that's a hack!
The pendulum is now beginning to swing the other way: Designers are asking how to TURN OFF equal height columns.
You can add align-items: flex-start to your #container_add_movies. Here's an example
to have the unequal columns in bootstrap 4, first of all it needs to know how it is making it equal heights of the columns,so the reason is the
align-items: stretch
to remove this property it need to add align-items: flex-start so for this I have added the class="align-items-start" and the issue is fixed,
Setting the child element that was causing the problem to flex:none did the trick for me.
I'm using flexbox to center the text in my div but that seems to make it so that the two lines of text, which are both p tags, aren't displaying with normal block properties (i.e. they are smooshing onto the same line instead of stacking, which is the desired result).
I am open to either removing flexbox, if I can get the text (the two p tags) within the div to align both vertically and horizontally or keeping flex and getting the p tags to each take up the full width of the div, like a block element.
The "my name is" part should be on top of the actual name:
HTML:
<div class='nametag' id='bernie'>
<p class='hello'>Hello, my name is</p>
<p class='name'>Bernie</p>
</div>
<div class='nametag' id='carly'>
<p class='hello'>Hello, my name is</p>
<p class='name'>Carly</p>
</div>
CSS:
.nametag {
border: 2px solid red;
height: 6em;
width: 10em;
color: red;
background-color: white;
bottom: 30%;
position: absolute;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-align: center;
-webkit-align-items: center;
-webkit-box-align: center;
align-items: center;
justify-content: center;
flex-flow: row-wrap;
}
.hello {
font-size: .7em;
display: flex;
flex-flow: row-wrap;
width: 5em;
}
.name {
font-size: 1.2em;
display: flex;
flex-flow: row-wrap;
width: 5em;
}
There are a few small problems.
You are using the compound property flex-flow, which lets you specify both the flex-direction and flex-wrap values in one rule (the same way you can say border: 1px solid black;). Now, the value you have here is row-wrap, which is actually being ignored because it's not a valid value (it would be row wrap -- one value for direction, one for wrap mode).
But! You don't want row anyway. Row layout is default, which is why you're getting the first item to the left of the second. You want column. You can set this by either using flex-direction: column or flex-flow: column wrap (assuming you want wrapping to be possible).
Final note: you also set flex-flow and display: flex on the child elements. These rules both pertain to an element with flex children. If these elements are really just going to be <p> tags, you only need them on the .nametag ('flex parent') selector.
Take a look at this example
It has a flexbox container with flex-flow: row wrap; to wrap all items. This is almost what I want.
When it starts to wrap, item number 6 wraps to the second line:
1 2 3 4 5
6
But always I want to wrap at least two items when it starts to wrap so you'll never have a single items on a line:
1 2 3 4
5 6
While not the most elegant solution, you could wrap the last two elements in another flexbox:
<html>
<head>
<style>
.flex {
display: flex;
flex-wrap: wrap;
}
.flex > div {
flex: 1 0 auto;
padding: 20px;
text-align: center;
}
.flex .flex {
padding: 0;
flex-grow: 2;
}
</style>
</head>
<body>
<div class="flex">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div class="flex">
<div>5</div>
<div>6</div>
</div>
</div>
</body>
</html>
See a pen here: https://codepen.io/anon/pen/prodVd
I figured out a way to do it for inline Elements, however it will behave inconsistently across browsers when used with inline-blocks. Still not a solution, but maybe somebody can figure out a way to make it behave with inline-block elements.
.item {
display: inline;
}
.item::before {
content: ' ';
font-size: 0;
}
.item:last-child::before {
content: '';
}
Here is a Fiddle with it in action.
Here's an approach that should work under the constraint that the width of the element is fixed
Assuming the width is 50px:
.container {
display: flex;
flex-flow: row wrap;
}
.flex-item: {
width: 50px;
display: block;
}
.flex-item:nth-child(even) {
translateX(100%)
margin-left: -100px;
}
.flex-item:nth-child(odd) {
margin-right: 50px;
}
The trick is to basically move the "footprint" of every 2nd element into its predecessor (negative margin), still display it in its original place (translate) and having the predecessor eat the remaining space (positive margin) for the purpose of row-breaking.
You can try to wrap 2 sibling elements with flex container
Based on https://stackoverflow.com/a/30431565/6884587 which did not work due to syntactical and logical reasons, I figured out how to do it for preknown same width items.
.container {
display: flex;
flex-flow: row wrap;
justify-content: center;
/* gap: 5px <-- can be used for spacing */
}
.flex-item: {
width: 50px;
display: block;
}
.flex-item:last-child {
margin-left: -50px; /* consider gap in this value, if applicable */
}
.flex-item:nth-last-child(2) {
margin-right: 50px; /* consider gap in this value, if applicable */}
This way, the last and the next to last item literally end on the same pixel, causing them to wrap line together.
For not preknown, but same width items it is a little more complex, since setting the margin to a percentage value is based on the item parent's width.
This is a pretty simple question, I guess, but I can't get 3 items in the flex container to display in 2 rows, one in the first row and the other 2 in the second row. This is the CSS for the flex container. It displays the 3 items on a single line, obviously :)
div.intro_container {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
If flex-wrap is set to wrap, then the 3 items are displayed in a column. I thought the wrap setting was needed to display container items on several lines.
I've tried this CSS for the first container item, intending to have it occupy the whole of the first row, but it didn't work
div.intro_item_1 {
flex-grow: 3;
}
I've followed the instructions in "CSS-Tricks" but I'm really not sure which combination of commands to use. Any help would be very welcome as I'm puzzled by this.
You can do something like this:
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flex>div {
flex: 1 0 50%;
}
.flex>div:first-child {
flex: 0 1 100%;
}
<div class="flex">
<div>Hi</div>
<div>Hello</div>
<div>Hello 2</div>
</div>
Here is a demo: http://jsfiddle.net/73574emn/1/
This model relies on the line-wrap after one "row" is full. Since we set the first item's flex-basis to be 100% it fills the first row completely. Special attention on the flex-wrap: wrap;
The answer given by Nico O is correct. However this doesn't get the desired result on Internet Explorer 10 to 11 and Firefox.
For IE, I found that changing
.flex > div
{
flex: 1 0 50%;
}
to
.flex > div
{
flex: 1 0 45%;
}
seems to do the trick. Don't ask me why, I haven't gone any further into this but it might have something to do with how IE renders the border-box or something.
In the case of Firefox I solved it by adding
display: inline-block;
to the items.
For SCSS file you can write this way:
.flex {
display: flex;
flex-direction: row;
flex-wrap: wrap;
>{
flex: 1 0 50%;
}
&:first-child{
flex: 0 1 50%;
}
}
<div class="flex">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
Output:
1 2
3
I'm trying to swap two divs' locations for responsive design (the site looks different depending on width of the browser/good for mobile).
Right now I have something like this:
<div id="first_div"></div>
<div id="second_div"></div>
But would it be possible to swap their placements to make it look like second_div is first, using CSS only? The HTML stays the same. I've tried using floats and stuff but it doesn't seem to work the way I want it to. I don't want to use absolute positioning because the heights of the divs are always changing. Are there any solutions, or is there just no way to do this?
Someone linked me this: What is the best way to move an element that's on the top to the bottom in Responsive design.
The solution in that worked perfectly. Though it doesn’t support old IE, that doesn’t matter for me, since I’m using responsive design for mobile. And it works for most mobile browsers.
Basically, I had this:
#media (max-width: 30em) {
.container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
/* optional */
-webkit-box-align: start;
-moz-box-align: start;
-ms-flex-align: start;
-webkit-align-items: flex-start;
align-items: flex-start;
}
.container .first_div {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
-ms-flex-order: 2;
-webkit-order: 2;
order: 2;
}
.container .second_div {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
}
This worked better than floats for me, because I needed them stacked on top of each other and I had about five different divs that I had to swap around the position of.
The accepted answer worked for most browsers but for some reason on iOS Chrome and Safari browsers the content that should have shown second was being hidden. I tried some other steps that forced content to stack on top of each other, and eventually I tried the following solution that gave me the intended effect (switch content display order on mobile screens), without bugs of stacked or hidden content:
.container {
display:flex;
flex-direction: column-reverse;
}
.section1,
.section2 {
height: auto;
}
This question already has a great answer but in the spirit of exploring all possibilities here is another technique to reorder dom elements whilst still allowing them to take up their space, unlike the absolute positioning method.
This method works in all modern browsers and IE9+ (basically any browser that supports display:table) it has a drawback that it can only be used on a max of 3 siblings though.
//the html
<div class='container'>
<div class='div1'>1</div>
<div class='div2'>2</div>
<div class='div3'>3</div>
</div>
//the css
.container {
display:table;
}
.div1 {
display:table-footer-group;
}
.div2 {
display:table-header-group;
}
.div3 {
display:table-row-group;
}
This will reorder the elements from 1,2,3 to 2,3,1. Basically anything with the display set to table-header-group will be positioned at the top and table-footer-group at the bottom. Naturally table-row-group puts an element in the middle.
This method is quick with good support and requires much less css than the flexbox approach so if you are only looking to swap a few items around for a mobile layout for example then dont rule out this technique.
You can check out a live demo on codepen: http://codepen.io/thepixelninja/pen/eZVgLx
This solution worked for me:
Using a parent element like:
.parent-div {
display:flex;
flex-direction: column-reverse;
}
In my case I didn't have to change the css of the elements that I needed to switch.
In some cases you can just use the flex-box property order.
Very simple:
.flex-item {
order: 2;
}
See: https://css-tricks.com/almanac/properties/o/order/
Using CSS only:
#blockContainer {
display: -webkit-box;
display: -moz-box;
display: box;
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
box-orient: vertical;
}
#blockA {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
box-ordinal-group: 2;
}
#blockB {
-webkit-box-ordinal-group: 3;
-moz-box-ordinal-group: 3;
box-ordinal-group: 3;
}
<div id="blockContainer">
<div id="blockA">Block A</div>
<div id="blockB">Block B</div>
<div id="blockC">Block C</div>
</div>
Assuming Nothing Follows Them
If these two div elements are basically your main layout elements, and nothing follows them in the html, then there is a pure HMTL/CSS solution that takes the normal order shown in this fiddle and is able to flip it vertically as shown in this fiddle using one additional wrapper div like so:
HTML
<div class="wrapper flipit">
<div id="first_div">first div</div>
<div id="second_div">second div</div>
</div>
CSS
.flipit {
position: relative;
}
.flipit #first_div {
position: absolute;
top: 100%;
width: 100%;
}
This would not work if elements follow these div's, as this fiddle illustrates the issue if the following elements are not wrapped (they get overlapped by #first_div), and this fiddle illustrates the issue if the following elements are also wrapped (the #first_div changes position with both the #second_div and the following elements). So that is why, depending on your use case, this method may or may not work.
For an overall layout scheme, where all other elements exist inside the two div's, it can work. For other scenarios, it will not.
Simple flexbox solution utilizing the order-property:
.container {
display: flex;
flex-direction: column;
}
.first {
order: 3;
}
.second {
order: 2;
}
<div class="container">
<div class="first">First</div>
<div class="second">Second</div>
<div class="third">Third</div>
</div>
assuming both elements have 50% width, here is what i used:
css:
.parent {
width: 100%;
display: flex;
}
.child-1 {
width: 50%;
margin-right: -50%;
margin-left: 50%;
background: #ff0;
}
.child-2 {
width: 50%;
margin-right: 50%;
margin-left: -50%;
background: #0f0;
}
html:
<div class="parent">
<div class="child-1">child1</div>
<div class="child-2">child2</div>
</div>
example: https://jsfiddle.net/gzveri/o6umhj53/
btw, this approach works for any 2 nearby elements in a long list of elements. For example I have a long list of elements with 2 items per row and I want each 3-rd and 4-th element in the list to be swapped, so that it renders elements in a chess style, then I use these rules:
.parent > div:nth-child(4n+3) {
margin-right: -50%;
margin-left: 50%;
}
.parent > div:nth-child(4n+4) {
margin-right: 50%;
margin-left: -50%;
}
Yesterday ran into the same problem. Grid areas worked out great in my case:
.content-body {
display: grid;
grid-template-areas: " left right ";
grid-template-columns: 1fr 1fr;
}
.first_div {
grid-area: right;
}
.second {
grid-area: left;
}
You don't need anything fancy. Make a copy of your second div, and place it on top. Like this
<div id="second_div_copy"></div>
<div id="first_div"></div>
<div id="second_div"></div>
Give the second_div_copy display: none when you want first div to appear on top. Give the second_div_copy display: block, and the second_div display: none when you want the second div to appear on top.
It's really that simple. Or am I missing something ?