self adjusting layout using flex - html

* {
border: none;
font-family: monospace;
}
html, body {height: 100%;}
body {
display: flex;
align-items: center;
padding: 10px;
}
.container {
background: #eee;
box-shadow: 0 10px 30px -10px rgba(0,0,0,.45);
margin: auto;
width: 500px;
padding: 30px 20px 20px;
}
/* main css starts here */
.row {
display: flex;
margin-bottom: 10px
}
input {
flex: 1;
padding: 2px 10px;
margin-left: 10px;
border: dotted 1px #bbb;
border-radius: 20px;
background: #fefefe
}
<div class="container">
<div class="row">
<label>hey ya!</label>
<input/>
</div>
<div class="row">
<label>how are you?</label>
<input/>
</div>
<div class="row">
<label>i am fine</label>
<input/>
</div>
</div>
I want all labels to have same width, where width is exactly equal to the content width of widest label. I want layout to automatically adjust all label width.
Right now, you can see the width of labels is different. If I want same width label then I have to either add a flex-basis property to label items or give them a min-width value. I dont want to do either of them as then I have to manually first check the width of widest label element and layout will break if I change letter spacing or choose some wide font.
In XUL there is a vbox element which helps to make such kind of layout and in html I guess table can be used to do so but I am looking for a flexbox solution.

Just as Niet pointed out, use display: table
* {
border: none;
font-family: monospace;
}
html, body {height: 100%;}
body {
display: flex;
align-items: center;
padding: 10px;
}
.container {
display: table;
background: #eee;
box-shadow: 0 10px 30px -10px rgba(0,0,0,.45);
margin: auto;
padding: 30px 20px 20px;
}
/* main css starts here */
.row {
display: table-row;
margin-bottom: 10px
}
label {
display: table-cell;
padding: 5px;
}
input {
padding: 2px 10px;
margin-left: 10px;
border: dotted 1px #bbb;
border-radius: 20px;
background: #fefefe
}
<div class="container">
<div class="row">
<label>hey ya!</label>
<input/>
</div>
<div class="row">
<label>how are you?</label>
<input/>
</div>
<div class="row">
<label>i am fine</label>
<input/>
</div>
</div>

Related

Adjust <p> width to its text content

This seems like an easy question but I've been trying to fix it for a couple of hours now and I still cannot find a solution. I have a box with two columns like in here:
p {
margin: 0;
padding: 0;
margin-right: 2px;
}
.container {
padding: 5px;
width: 90%;
height: 200px;
margin: auto;
border: 1px black solid;
}
.row {
display: flex;
justify-content: space-between;
width: 100%;
}
.half {
width: 50%;
}
.left-col {
display: flex;
}
.right-col {
text-align: right;
}
.tooltip {
position: relative;
border: 1px black solid;
border-radius: 100%;
width: 14px;
height: 14px;
font-size: 12px;
display: flex;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="row">
<div class="half">
<div class="left-col">
<p>Username picked on regitration:</p>
<div class="tooltip">?</div>
</div>
</div>
<div class="half">
<p class="right-col">
John WithLongSurname
</p>
</div>
</div>
</div>
The problem is, that when I open the page on mobiles, the text on the left column is too long and it wraps (which is good), but its width still takes a whole column, so the tooltip is not next to the text but in the center of the box (it sticks to the right side of the column). Example:
I tried to add width: min-content to the "label" class, but then the whole paragraph just collapses to the smallest possible width. How can I adjust the width of the paragraph, so it will take only as much width as it needs to, so the tooltip will always be next to it?
It is because you are using display: flex; for the .left-col class. By default it will distribute the width automatically and evenly.
Try the styling below to see if it works:
p {
margin: 0;
padding: 0;
margin-right: 2px;
}
.container {
padding: 5px;
width: 90%;
height: 200px;
margin: auto;
border: 1px black solid;
}
.row {
display: flex;
justify-content: space-between;
width: 100%;
}
.half {
width: 50%;
}
.left-col {
display: inline;
}
.right-col {
text-align: right;
}
.tooltip {
position: relative;
border: 1px black solid;
border-radius: 100%;
width: 14px;
height: 14px;
font-size: 12px;
display: inline;
}
p.label {
width: auto;
}
<div class="container">
<div class="row">
<div class="half">
<div class="left-col">
<p class="label">Username picked on regitration:
<span class="tooltip">?</span>
</p>
</div>
</div>
<div class="half">
<p class="right-col">
John WithLongSurname
</p>
</div>
</div>
</div>

How to start a new line and align the newline with another item within flexbox?

I have a flexbox with different items inside.
When it wraps onto a new line I want to align this new line with the 2nd item on the first row of the flexbox, but I can't figure out how to do this. The width of the elements will be dynamic, based on the text inside.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
<div class="parent">
<div class="unique_element">First</div>
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
When it wraps onto a new line I want to align this new line with the 2nd item on the first row of the flexbox.
So, the real question is: How to re-arrange flex items when wrapping occurs?
Since HTML and CSS, by themselves, have no concept of when elements wrap, they have no control of this situation. You have to handle it, either with media queries or JavaScript.
Once you've selected your method for detecting the wrap, you can use the order property to re-arrange the items.
To expand on #MichaelBenjamin's fantastic answer:
Since HTML and CSS, by themselves, have no concept of when elements wrap, they have no control of this situation. You have to handle it, either with media queries or JavaScript.
You can work around this by setting a new parent element and nest the unique element as the first child. Set this new master-parent to display: flex;.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
height: 27px;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
.master-parent {
display: flex;
width: 400px;
}
<div class="master-parent">
<div class="unique_element">First</div>
<div class="parent">
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
</div>
You can create two divs inside the parent div, one that holds the unique element and one that holds generic children. That's how you get the separation
<div class="parent">
<div class="unique-wrapper">
<div class="unique_element">First</div>
</div>
<div class="child-wrapper">
<div class="child">Second</div>
<div class="child">Third</div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>
</div>
Style the CSS as shown. Note .unique-wrapper has flex: 3 because you set the width of the element as 30%.
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
width: 300px;
}
.unique_element {
background-color: Crimson;
padding: 10px 10px 10px 10px;
}
.unique-wrapper, .child-wrapper {
border: none;
margin: 0;
}
.unique-wrapper {
flex: 3;
}
.child-wrapper {
flex: 7;
display: flex;
flex-wrap: wrap;
}
.child {
width: auto;
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
Here is my codepen if you want to play with the code.
create a dummy element for spacing
div {
font-family: arial, sans-serif;
margin: 5px;
color: white;
border: 1px dotted black;
}
.parent {
display: flex;
flex-wrap: wrap;
width: 300px;
}
.unique_element {
background-color: Crimson;
width: 30%;
padding: 10px 10px 10px 10px;
}
.child {
background-color: CornflowerBlue;
padding: 10px 10px 10px 10px;
}
.hideme{
visibility:invisible;
background-color:white;
border:none;
}
<div class="parent">
<div class="unique_element">First</div>
<div class="child">Second</div>
<div class="child">Third</div>
<div class="unique_element hideme"></div>
<div class="child">Fourth</div>
<div class="child">Fifth</div>
</div>

place button at the right of div

here is how my screen should look like:
the orange button should be on the right of the "dashboard-detail-body" and have margins to the top, left, and bottom ("dashboard-container")
this is what I tried:
<div class="dashboard-detail-body">
<div style="float: right; margin-right: 10px; margin-top: 15px;">
{{ui-5/button label="click me"}}
</div>
<div class="dashboard-container">
but I do not get the desired behavior - no margin bottom (the orange button is overlapping with the bottom div)
margin-bottom, did not solve it, how can I get the desired behavior?
The issue is with the float: right; style. This makes the element overlap.
You can solve this issue by using flex-box, with the following code:
.dashboard-detail-body{
display: flex;
flex-direction:column;
}
.align-right{
align-self: flex-end;
}
<div class="dashboard-detail-body">
<div class="align-right">
I am right
</div>
<div class="dashboard-container">
<p>a<p>
<p>b<p>
<p>c<p>
</div>
</div>
Though it was difficult to understand and recreate your problem from the available data, I assume that you want to align a button center-right inside the container. You can use flexbox to align elements inside a parent.
.container {
height: 200px;
border: solid 1px #333;
display: flex;
justify-content: right;
align-items: center;
}
button.orange {
border: none;
outline: none;
height: 1.5rem;
/* optional basic styling */
background: orange;
color: #fff;
}
<div class="container">
<button class="orange">Click Me</button>
</div>
You can try with css grid:
.dashboard-detail-body{
display: grid;
grid-template-columns: 1fr;
justify-items: center;
border: 1px solid grey;
border-radius: 2em;
}
.right{
justify-self: end;
margin: 1em 3em 1em 1em;
background-color: orange;
padding: .5em;
border-radius: .5em;
}
.dashboard-container {
display: flex;
justify-content: center;
align-items: start;
border: 1px dashed grey;
border-radius: 1.5em;
margin-bottom: 2em;
width: 95%;
height: 200px;
}
.dashboard-container > p {
padding: 1.5em 2em;
margin: 1em;
border: 1px solid grey;
border-radius: .5em;
}
<div class="dashboard-detail-body">
<div class="right">
click me
</div>
<div class="dashboard-container">
<p></p>
<p></p>
<p></p>
</div>
</div>
As you are shrinking your div with float right it frees space on the left. The clear property doesn't work.
So the solution I came up with is to keep the div full & use a button
.dashboard-detail-body {
background: #eeeeee;
border: 3px solid #bbbbbb;
border-radius: 20px;
height: 80vh;
width: 80%;
min-height: 40rem;
min-width: 45rem;
margin: auto;
}
.btn-area {
height: 5rem;
width: 100%;
/* border: 1px solid red; */
}
.btn {
background: #ff9900;
padding: 10px 15px;
border-radius: 10px;
border: 2px solid #9c7842;
/* clear: left; */
/* display: inline-block; */
float: right;
margin-right: 25px;
margin-top: 25px;
}
.dashboard-container {
border: 3px solid #bbbbbb;
margin: auto;
width: 75%;
height: 75%;
border-radius: 20px;
display: flex;
justify-content: center;
/* align-items: center; */
}
.box {
border: 3px solid #bbbbbb;
width: 6.5rem;
height: 6.5rem;
border-radius: 20px;
float: left;
margin: 1rem;
}
<div class="dashboard-detail-body">
<div class="btn-area">
<button class="btn">Click Me</button>
</div>
<div class="dashboard-container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>

How to create white space between words and keep design responsive

I am trying to create a box with a list of descriptive characteristics to the left and corresponding values to the right. I want it to be responsive also. First I tried to create two Unordered lists and float one right and the other left but this does not work when the browser becomes narrower.
So now I have tried to use the method below where I just add many to put space between the characteristic on the left and its value on the right.
This works if you specify the screen size with media queries but I'm not sure how it will display for a user who has an extra large screen that I have not written a media query for.
How can I create this space between words?
.gallery {
height: max-content;
background: black;
border-radius: 10px;
border: solid 2px #f0c330;
overflow: hidden;
color: white;
flex: 0 1 48%;
margin-left: 1%;
margin-right: 1%;
<div class="gallery">
<h2>Statistics</h2>
<p class="pdesc"> Height 6ft <br/> Age
36</p>
</div>
Use flexbox for each row, and use justify-content: space-between to space out the items on the far ends of each box. Then you can adjust the width of the boxes accordingly, e.g. 30%:
.gallery {
background: #000;
border-radius: 10px;
border: solid 2px #f0c330;
color: #fff;
flex: 0 1 48%;
margin-left: 1%;
margin-right: 1%;
padding: 10px;
}
.gallery h2{
margin-top:0;
}
.pdesc{
display: flex;
justify-content: space-between;
width: 30%;
}
<div class="gallery">
<h2>Statistics</h2>
<div class="pdesc">
<span>Height</span>
<span>6ft</span>
</div>
<div class="pdesc">
<span>Age</span>
<span>36</span>
</div>
</div>
Ugh!
I'd do something like this:
<div class="gallery">
<h2>Statistics</h2>
<p class="pdesc"><span>Height</span><span>6ft</span></p>
<p class="pdesc"><span>Age</span><span>36</span></p>
</div>
<style>
.gallery {
height:max-content;
background: black;
border-radius: 10px;
border: solid 2px #f0c330;
overflow:hidden;
color: white;
flex: 0 1 48%;
margin-left: 1%;
margin-right:1%;
}
p {
width:100%;
display:flex;
justify-content:space-between;
}
</style>
No messing with variable at all.
You could use span tags for the text parts and apply display: flex; justify-content: space-between; to the p tags:
.gallery {
height: max-content;
background: black;
border-radius: 10px;
border: solid 2px #f0c330;
overflow: hidden;
color: white;
flex: 0 1 48%;
margin-left: 1%;
margin-right: 1%;
padding: 12px;
}
.pdesc {
display: flex;
justify-content: space-between;
}
<div class="gallery">
<h2>Statistics</h2>
<p class="pdesc"><span>Height</span><span>6ft</span></p>
<p class="pdesc"><span>Age</span><span>36</span></p>
</div>

How do I make flex items shrink to their smallest fitting size, but the same size?

I'm trying to make a row of buttons, where the buttons will be the same size, but as small as possible - so each being the same size as the largest button.
How can I do this?
div {
border: solid 1px black;
margin: 5px;
padding: 5px;
background-color: #fff;
}
.container {
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
}
.item {
background-color: #eef;
flex: 0 1 auto;
white-space: nowrap;
}
<div class="container">
<div class="item">this one is quite long</div>
<div class="item">short</div>
</div>
flexbox can do a lot but not all. For this grid would be good, but since it lacks good browser support, its older "version" table might be an option.
Here is a script free, dynamic solution, using display: inline-table.
.container,
.item {
border: solid 1px black;
margin: 5px;
padding: 5px 0 5px 5px;
background-color: #fff;
}
.container {
text-align: right;
}
.wrap {
display: inline-table;
border-spacing: 10px 5px;
}
.item {
background-color: #eef;
display: table-cell;
width: 50%;
white-space: nowrap;
text-align: left;
}
<div class="container">
<div class="wrap">
<div class="item">this one is quite long</div>
<div class="item">shorter</div>
</div>
</div>
I don't think this is possible with flexbox, but for what it's worth, this can be achieved with the CSS Grid Layout Module.
.container,
.item {
border: solid 1px black;
margin: 5px;
padding: 5px 0 5px 5px;
background-color: #fff;
}
.container {
text-align: right;
}
.wrap {
display: inline-grid;
grid-template-columns: 1fr 1fr;
}
.item {
background-color: #eef;
text-align: left;
}
<div class="container">
<div class="wrap">
<div class="item">this one is quite long</div>
<div class="item">shorter</div>
</div>
</div>
Codepen demo
Here's the relevant CSS:
.container {
text-align: right;
}
.wrap {
display: inline-grid;
grid-template-columns: 1fr 1fr;
}
It's worth noting here that flex-grow: 1 (for flex items) works a bit different here than flexible lengths - 1fr for css grids.
.container,
.item {
border: solid 1px black;
margin: 5px;
padding: 5px 0 5px 5px;
background-color: #fff;
}
.container {
text-align: right;
}
.wrap {
display: inline-flex;
}
.item {
background-color: #eef;
text-align: left;
flex: 1;
}
<div class="container">
<div class="wrap">
<div class="item">this one is quite long</div>
<div class="item">shorter</div>
</div>
</div>
It's almost identical code - except that flex-grow seems to wrap the first item's long text on to a new line.