I have a simple HTML code which contains three button inside a flex div as bellow;
When a user click on any of the buttons, that button will have the active class.
.box {
width: 100%;
background-color: red;
text-align: center;
}
.flexbox {
width: 100%;
justify-content: center;
}
.active {
background-color: yellow;
}
<div class="box">
<h4>HELLO</h4>
<div class="flexbox">
<button class="active">ONE</button>
<button>TWO</button>
<button>THREE</button>
</div>
</div>
What I need to achieve here is the button contain the active class should always be centre aligned in side the flex box.
According to the above, the button ONE has the active class and it should be centre aligned in side the flexbox and other two buttons should go right.
You can get the idea from the image below
NOTE: Preferred to solve this with use CSS only.
If it's only 3 buttons here is an idea using CSS grid:
.box {
background-color: red;
text-align: center; /* center the grid */
}
.flexbox {
display: inline-grid;
grid-template-columns: repeat(5, 1fr); /* 5 columns */
justify-content: center; /* center the columns */
gap: 5px;
}
.active {
grid-column: 3; /* active always on the middle */
}
/* we need a "hacky" code for the second case */
.active:nth-child(2) {
grid-area:1/1;
transform:translate(calc(200% + 10px)); /* 10px = 2xgap */
}
.active:nth-child(2) ~ :last-child {
grid-column:4;
}
<div class="box">
<h4>HELLO</h4>
<div class="flexbox">
<button class="active">ONE</button>
<button>TWO</button>
<button>THREE</button>
</div>
</div>
<div class="box">
<h4>HELLO</h4>
<div class="flexbox">
<button >ONE</button>
<button class="active">TWO</button>
<button>THREE</button>
</div>
</div>
<div class="box">
<h4>HELLO</h4>
<div class="flexbox">
<button >ONE</button>
<button >TWO</button>
<button class="active">THREE</button>
</div>
</div>
Related
I'm programming a web application with collapsible sidebar inside a CSS grid. The CSS grid divides the whole UI into sections, and the sidebar panel is a sub-component of one of those sections.
The issue I am running into is that I want the side panel to automatically shrink to the minimum size of it's contents, which it does fine until it's added to a CSS grid cell, at which point it expands to fill the entire cell.
Here is a quick example of the issue:
<style>
#myGrid{
display: grid;
grid-template-areas:
"g1 g2";
}
#panel{
grid-area: g2;
display: inline-block;
background: #FFAAAA;
height: 100%;
width: auto;
min-width: minmax(0, 1fr);
}
#panelContents{
display: flex;
flex-direction: row;
height: 100%;
}
#collapseArrow{
align-self: center;
right: 0;
top: 50%;
}
#block{
grid-area: g1;
width: 200px;
height: 100%;
background: #AAAAFF;
}
</style>
<body>
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">
Item1
</div>
<div class="item">
Item2
</div>
<div class="item">
Item3
</div>
<div class="item">
Item4
</div>
<div class="item">
Item5
</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>
</body>
Any idea how to solve this? I am trying to get the red panel to shrink to fit it's contents. I tried changing the min-width to 0, but that didn't seem to help.
EDIT: This is a more complex UI for an HTML5 game engine. The left grid cell is an asset browser, and the red panel is a simple properties panel for the right editor window (right grid cell), which I'm trying to display only on the left portion of the cell, so the rest of the right cell can be the editor window.
Use the other column to squeeze the panel down to its content width.
#myGrid {
display: grid;
grid-template-columns: 1fr auto; /* 1fr consumes all free space on the row */
grid-template-areas: "g1 g2";
}
#block {
grid-area: g1;
background: #AAAAFF;
}
#panel {
grid-area: g2;
background: #FFAAAA;
}
#panelContents {
display: flex;
}
#collapseArrow {
align-self: center;
}
<div id="myGrid">
<div id="block">
Contents
</div>
<div id="panel">
<div id="panelContents">
<div id="collapseContents">
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
</div>
<div id="collapseArrow"><</div>
</div>
</div>
</div>
I have two divs (div1 and div2) side by side and I would like to place a third div (div3) under div2.
I've tried adding a margin to div3 to try and line it up, but div1 width is dynamic. I've also tried floating div3 to the right but then the content is too far and doesn't line up with the start of div2 like in the image above
.row {
display: flex;
}
.div1 {
margin-right: 1em;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
The default behaviour is div3 being under div1. I am trying to put div3 below div 2
You can do this with below:
.wrapper {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
.div {
flex-basis: 50%;
min-height: 100px;
}
.div1 {
background: red;
}
.div2 {
background: blue;
}
.div3 {
background: aqua;
}
<div class="wrapper">
<div class="div div1">div1</div>
<div class="div div2">div2</div>
<div class="div div3">div3</div>
</div>
And here is a codepan
Use float and inline-block:
[class*="div"] {
display:inline-block;
border:2px solid;
}
.div1 {
float:left;
margin-right: 1em;
margin-bottom:10px; /*mandatory margin to push the div3*/
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
You can make use of the CSS Grid structure. In this way you can have all child elements inside a single parent container.
.row {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 5px;
grid-row-gap: 5px;
}
.div1 {
grid-area: 1 / 1 / 2 / 2;
}
.div2 {
grid-area: 1 / 2 / 2 / 3;
}
.div3 {
grid-area: 2 / 2 / 3 / 3;
}
/* Snippet styling */
.row > div {
background: #6A67CE;
color: white;
text-align: center;
text-transform: capitalize;
font-family: sans-serif;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
<div class="div3">
<p> some content under div2 </p>
</div>
</div>
Here is a flex solution, you can use the slider to change the width of the left box to see that the width doesn't matter.
In case you are not familiar with flex, here is what happens.
display: flex; tells the container to act as a flex container, flex is just another display behavior just like float.
flex-flow: row wrap;, now that the container is flex, tells the children to display in a row, and wrap if necessary, not in this case.
That is all, after adding two boxes in the right div, and set some demo width and height, we are done.
window.addEventListener('DOMContentLoaded', e => {
let left = document.querySelector('.left')
let range = document.querySelector('.range')
range.addEventListener('input', e => {
left.style.width = e.target.value + 'px'
})
})
div {
border: 3px solid green;
}
.container,
.right {
border: none;
}
.container {
display: flex;
flex-flow: row wrap;
}
.left,
.one,
.two {
min-width: 50px;
min-height: 50px;
}
.left {
margin-right: 1em;
}
.one {
min-width: 80px;
}
.two {
margin-top: 1em;
}
<div class="container">
<div class="left"></div>
<div class="right">
<div class="one"></div>
<div class="two"></div>
</div>
</div>
<input class="range" type="range" min="50" max="300"></input>
Since div do not share the same parent , you could use display:contents and set a grid-layout one level upper , unfortunately, display:contents is not yet supported every where .
here is an example (body is the wrapper and .row not seen anymore)
body {
display: grid;
grid-template-columns: auto 1fr;
grid-gap: 10px;
}
.row {
display: contents;
/* removed from the tree */
}
div {
border: solid;
/* show me */
grid-column: 2;
/* make it the defaut column position */
width: max-content;
}
.div1 {
grid-column: 1;
/*a single reset enough here */
}
#supports (display:grid) {
.disclaimer {
display: none;
}
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
<p class="disclaimer">Your browser do not support <code>display:contents</code>.</p>
Another possibility is the table-layout algorythm
example with display:table (widely supported) , but every cell of each columns are of the same width.
body {
display: table;
border-spacing: 10px;
}
.div3,
.row {
display: table-row;
}
.row>div,
.div3>p,
.div3::before {
display: table-cell;
border: solid;
}
.div3::before {/* it stands in column 1 */
content: '';
border: none;
}
<div class="row">
<div class="div1">
<p> some content with unknown width</p>
</div>
<div class="div2">
<p> some content </p>
</div>
</div>
<div class="div3">
<p> some content that should be under div2 </p>
</div>
Nothing is perfect ;)
hi i coded this if that helps
.first-container {
display: flex;
flex-direction: row;
}
.first-container div{
margin: 10px;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
<div class="container">
<div class="first-container">
<div class="first">first</div>
<div class="second">second</div>
</div>
<div class="third">third</div>
</div>
How can I get the content section to wrap nicely to the right of the image using flexbox?
.container {
display: flex;
align-items:center;
flex-wrap:wrap; /* we force a wrap so textarea is in the next line*/
}
.content {
flex-grow: 1;
}
textarea {
flex-basis: 100%;
margin-left:80px; /* use margin to adjust, change this value depending the icon and image width */
}
img {
border-radius: 30px;
margin: 0 10px;
}
<div class="container">
<div>
x
</div>
<!-- better remove the div around the image, it's useless and avoid having a white space issue -->
<img src="http://via.placeholder.com/50x50">
<div class="content">
<div>Brad</div>
<div>When this text is long it goes to the next line and it doesn't wrap nicely. It should stay right of the image</div>
</div>
<textarea></textarea>
</div>
Your css need to be changed, look at the new code bellow:
.container {
display: flex;
align-items:center;
flex-wrap:wrap; /* we force a wrap so textarea is in the next line*/
}
.content {
flex: 1;
}
textarea {
flex-basis: 100%;
margin-left:80px; /* use margin to adjust, change this value depending the icon and image width */
}
img {
border-radius: 30px;
margin: 0 10px;
}
<div class="container">
<div>
x
</div>
<!-- better remove the div around the image, it's useless and avoid having a white space issue -->
<img src="http://via.placeholder.com/50x50">
<div class="content">
<div>Brad</div>
<div>When this text is long it goes to the next line and it doesn't wrap nicely. It should stay right of the image</div>
</div>
<textarea></textarea>
</div>
You can also use display: grid to achieve your layout.
Example:
.container {
display: grid;
grid-template-columns: 10px 50px 1fr;
grid-template-rows: 1fr auto;
grid-gap: 0 10px;
}
img {
border-radius: 30px;
}
textarea {
grid-row: 2;
grid-column: 3
}
.close {
margin: auto;
}
<div class="container">
<div class="close">
x
</div>
<img src="http://via.placeholder.com/50x50">
<div class="content">
<div>Brad</div>
<div>When this text is long it goes to the next line and it doesn't wrap nicely. It should stay right of the image</div>
</div>
<textarea></textarea>
</div>
I have a header with 2 rows of 2 Foundation columns of content, as below:
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
HEADER
</div>
<div class="large-6 columns">
menu
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
The .header height is dynamic and not set. I want the .image element to take up 100% of the remaining vertical space.
eg:
To that affect I have tried using flex and flex-grow, eg:
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.image-container {
flex-grow: 1;
}
but had no luck, see fiddle: https://jsfiddle.net/9kkb2bxu/46/
Would anyone know how I could negate the dynamic height of the header from the 100vh of the image container?
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
border: 1px solid black;
display: flex;
}
.image {
background-color: red;
flex-grow: 1;
width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet"/>
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
Set the second row to take up the rest of the remaining height with flex: 1 and make sure you nest that flex with display: flex:
.row.target-row {
flex: 1;
display: flex;
}
Set the .image-container to 100% height of its column parent.
.image-container {
height: 100%;
}
By default both columns will expand. Stop the left column from expanding with:
.large-5 {
align-self: flex-start;
}
(flex-start reference: https://stackoverflow.com/a/40156422/2930477)
Complete Example
.wrapper {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
border: 1px solid black;
background-color: #ccc;
}
.row {
width: 100%;
}
.header {
background-color: green;
}
.info {
background-color: yellow;
border: 1px solid #ccc;
}
.image-container {
height: 100%;
background-color: red;
}
.large-5 {
align-self: flex-start;
}
.row.target-row {
flex: 1;
display: flex;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet" />
<div class="wrapper">
<div class="header row">
<div class="large-6 columns">
<h1>
HEADER
</h1>
</div>
<div class="large-6 columns">
<h1>
menu
</h1>
</div>
</div>
<div class="row target-row">
<div class="large-5 none show-for-medium columns info">
Some information to the left
</div>
<div class="large-7 columns">
<div class="image-container">
<div class="image">
image to the right
</div>
</div>
</div>
</div>
</div>
flex-grow only applies to flex children.
.image-container isn't a direct child of a display: flex element, so that property has no effect.
Plus, it affects the flex axis, which is not what you want.
Instead, you need to put those two elements in their own flex row, and use align-items (on the parent) and align-self (on either child) so that the first one aligns (on the cross axis) to flex-start (stick to top) and the second one to stretch.
You'll also want that flex row (parent) to have flex-grow: 1 so that it stretches along the vertical flex axis of its parent (.wrapper) to fill the rest of the page (otherwise, the grandchild will have nothing to stretch to).
For more information, read a good flex tutorial.
div.wrapper > div:not(.header).row {
flex: 1; /* 1 */
display: flex; /* 1 */
}
div.large-7.columns {
display: flex; /* 2 */
}
div.image-container { /* 3 */
flex: 1;
}
div.large-5.show-for-medium { /* 4 */
align-self: flex-start;
}
jsFiddle
Notes:
flex container and items consume all remaining height of respective parents
give children full height (via align-items: stretch initial setting)
flex item consumes all available width
yellow box does not need to expand to full height; now set to content height
Let i have a several number of buttons
<button ng-repeat="a in graphdata" class="inline">
I need to align all these buttons in a line, and all buttons should be visible, and it should adjust its width when new button is getting added.
Button should be attached to each other.
You can use flexbox
$('.new').click(function() {
$('.element').append('<button class="inline">Button</button>');
});
.element {
display: flex;
}
button {
flex: 1;
background: white;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="new">Add new Button</button>
<div class="element">
<button class="inline">Button</button>
</div>
You should wrap your buttons with flex container.
<style>
.wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap; /* if you want buttons in several lines */
}
button {
min-width: 50px;
}
</style>
<div class="wrapper">
<button ng-repeat="a in graphdata" class="inline"></button>
</div>