Control height of flex element within flex-grid without affecting surrounding elements - html

I am using a flex grid to lay out information. I want to highlight one of the cells within the grid so that it stands out to users by adjusting the height of the respective cell. However, my attempts have not gotten far as adjusting the properties of once cell will thereby affect the surrounding cells.
In my fiddle below, I have a class .highlighted within .flexbox-2 that I would like to change. Basically, the row 1 of the second column would have a taller height than the first and third column, but all the borders will still be aligned. I was thinking to apply position: absolute and change its CSS there, but this does not prove fruitful. I'm wondering if there are other routes I can take.
Check this jsfiddle
Code:
* {
box-sizing: border-box;
}
body {
font-family: helvetica, serif;
}
.container {
display: -webkit-flex;
-webkit-flex-direction: row;
}
.flex {
display: flex;
flex-direction: column;
}
.flex-row {
flex: 1;
border: 1px solid;
}
.flexbox-1 {
-webkit-flex: 1;
border: solid 3px red;
}
.flexbox-2 {
-webkit-flex: 1;
border: solid 3px green;
height: 200px;
margin-left: 10px;
position: relative;
}
.highlighted {
position: absolute;
border: 1px solid yellow;
padding-top: 20px;
}
.flexbox-3 {
-webkit-flex: 1;
border: solid 3px blue;
height: 200px;
margin-left: 10px;
}
<div class="container">
<div class="flex flexbox-1">
<div class="flex-row">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
<div class="flex flexbox-2">
<div class="flex-row highlighted">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
<div class="flex flexbox-3">
<div class="flex-row">row 1</div>
<div class="flex-row">row 2</div>
<div class="flex-row">row 3</div>
</div>
</div>

If you want that first row to stick out above the other two columns, you could use a negative margin-top:
.highlighted {
border: 1px solid yellow;
margin-top: -10px;
padding-bottom: 10px;
}
Working Example

Related

HTML & CSS, how to center 3 divs inside a div?

I am trying to position 3 div in the center of another div but I'm having issues with the positioning. I tried using verticle-align, and negative margins but nothing seems to be working.
.float-container {
border: 3px solid red;
padding: 250px;
position: relative;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
float: left;
padding: 10px;
border: 2px solid red;
margin: 30px;
vertical-align: middle;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
example for my comment
vertical alignment is not avalaible for floatting elements. Nowdays, for this kind of layout, grid or flex are efficient, flexible and easy to put in action. This is not a float job ;)
.float-container {
border: 3px solid red;
display:flex;
align-items:center;
justify-content:center;
gap:30px;
min-height:500px;
position: relative;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
children only need now to be sized . alignement gap in between them is set from the flex parent. A min-height is given (500px inspirated from your padding 250px)
Remove the float: left; and in its place add display: flex;, justify-content: center;, align-items: center;, flex-direction: row;. For requirements like these, flex and grid are usually much simpler to implement.
.float-container {
display: flex;
padding: 250px;
position: relative;
align-items: center;
border: 3px solid red;
justify-content: center;
background-color: lightblue;
}
.float-child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
margin: 0 10px;
vertical-align: middle;
}
<div class="float-container">
<div class="float-child">
<div>Float Column 1</div>
</div>
<div class="float-child">
<div>Float Column 2</div>
</div>
<div class="float-child">
<div>Float Column 3</div>
</div>
</div>
An easy and "modern" way is to use Flexbox if there are no limitations being set as part of a requirement to use float. As an example:
.container {
border: 3px solid red;
padding: 20px;
background-color: lightblue;
display: flex;
justify-content: center;
align-items: center;
gap: 1rem;
}
.child {
width: 150px;
height: 150px;
padding: 10px;
border: 2px solid red;
}
<div class="container">
<div class="child">
Float Column 1
</div>
<div class="child">
Float Column 2
</div>
<div class="child">
Float Column 3
</div>
</div>

How the flex box item use the full width of its parent

.container {
width: 400px;
border: 2px solid red;
display: flex;
flex-flow: row wrap;
}
.item {
padding: 20px;
border: 1px solid blue;
width: 70px;
}
<div class="container">
<div class=item>Box 1</div>
<div class=item>Box 2</div>
<div class=item>Box 3</div>
<div class=item>Box 4</div>
<div class=item>Box 5</div>
</div>
My question, how can "Box 1", "Box 2", "Box 3" use the full width of the "container" class? and "Box 4" and "Box 5" will line up from below to the above box "Box 1" and "Box 2".
You have several ways to go about it; here are two ways:
Use flex-grow. If you add flex-grow: 1 to the item selector then the boxes on each row will take up the full width of the container. Note: With this solution you may want to make sure you have the same number of boxes per row, if you want these boxes to appear as a uniform grid. Otherwise the line with only one or two boxes will be stretched to fill the width of the container. So keep that in mind.
.container {
width: 400px;
border: 2px solid red;
display: flex;
flex-flow: row wrap;
}
.item {
padding: 20px;
border: 1px solid blue;
width: 70px;
flex-grow: 1;
}
Second option: Add margin: 0 auto; to the item selector, and they will fill the width by centering.
.container {
width: 400px;
border: 2px solid red;
display: flex;
flex-flow: row wrap;
}
.item {
padding: 20px;
border: 1px solid blue;
width: 70px;
margin: 0 auto;
}
This was actually kind of a brainteaser until I realized you need CSS grid instead of Flexbox :). There doesn't seem to exist a solution with Flexbox without adding "ghost divs", which isn't really a good option.
.container {
width: 400px;
border: 2px solid red;
display: grid;
grid-template-columns: 110px 110px 110px;
justify-content: space-between;
}
.item {
padding: 20px;
border: 1px solid blue;
}
<div class="container">
<div class=item>Box 1</div>
<div class=item>Box 2</div>
<div class=item>Box 3</div>
<div class=item>Box 4</div>
<div class=item>Box 5</div>
</div>

Split last tab width 50% and all other Tabs should fit in other 50% width

Need to split all tabs in such a way that. Last tab width will be 50% width and rest all tabs must fit in 50%. For now I gave fixed width: 16.65%. Would like to avoid it as there could 2 or 3 tabs excluding last tab.
Can this be achieved using display: flex ?
* {
margin: 0;
}
.wrapper {
overflow: hidden
}
.wrapper .tab {
float: left;
width: 16.65%;
text-align: center;
background: #ccc;
}
.wrapper .last-tab {
width: 50%;
background: #999
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
You can do it like this:
* {
margin: 0;
}
.wrapper {
display: flex; /* displays children inline */
overflow: hidden;
}
.wrapper > .tab {
flex: 1; /* enables growing of flex-items so they can fill flex-containers width / this is the shorthand way, but you can also use: flex: 1 1 auto; (i.e. flex-grow, flex-shrink, flex-basis) */
/*float: left;*/
/*width: 16.65%;*/
text-align: center;
background: #ccc;
}
.wrapper > .last-tab {
/*width: 50%;*/
flex: 0 1 50%; /* adjusted to take half of the wrappers width (i.e. initial width is set to 50%) */
background: #999;
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
If you want to do it pure flexbox way without the use of the width property.
try this
* {
margin: 0;
}
.wrapper {
overflow: hidden;
display: flex;
width: 100%;
}
.wrapper .tab {
width: calc(50%/3);
text-align: center;
background: #ccc;
}
.wrapper .last-tab {
width: 50%;
background: #999
}
<div class="wrapper">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
<div class="tab last-tab">Last Tab</div>
</div>
Take 2 blocks of 50-50%. Then you can easily divide inner divs as per your requirement.
Hope this helps you :)
* {
margin: 0;
}
.wrapper {
/*overflow: hidden*/
display:flex;
}
.wrapper .tab-container {
/*float: left;*/
display:flex;
width: 50%;
background: #ccc;
}
.wrapper .tab {
/*float: left;*/
display:flex;
width: 33.33%;
text-align: center;
}
.wrapper .last-tab {
width: 50%;
background: #999;
text-align: center;
}
<div class="wrapper">
<div class="tab-container">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="last-tab">Last Tab</div>
</div>

Background of div does not scroll with the contents

I have the following snippet of html that forms an X-Y scrollable listbox
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
It's working fine, with one problem, as the user scrolls from left to right, the background of the div seems to get left behind. It's as though the actual div only stretches the width of its parent, and the scrolling/overflow thing is "faked" somehow.
Why is this the case?
How do I address the problem? The behaviour I want is for all the items to appear to be the same width as the largest one.
Try adding a container <div class="items"> around the items set it to display:inline-block.
.items {
display: inline-block;
}
* {
font-family: "consolas";
}
.listbox {
border: 1px solid black;
padding: 4px;
width: 150px;
height: 200px;
display: flex;
flex-direction: column;
}
.caption {
font-weight: bold;
background-color: #aaf;
padding: 10px;
}
.content {
flex-grow: 1;
overflow: scroll;
}
.items {
display: inline-block;
}
.item {
background-color: #ddd;
padding: 2px;
padding-left: 6px;
margin-top: 4px;
white-space: nowrap;
}
<div class="listbox">
<div class="caption">Caption</div>
<div class="content">
<div class="items">
<div class="item">One</div>
<div class="item">Two</div>
<div class="item">Three (this has a longer bit)</div>
<div class="item">Four</div>
<div class="item">Five</div>
<div class="item">Six</div>
<div class="item">Seven</div>
<div class="item">Eight (so does this)</div>
<div class="item">Nine</div>
<div class="item">Ten</div>
</div>
</div>
</div>
Explanation: by default a block level element takes 100% width of the container no more than that, however an inline block will expand to content length if available e.g. in a scrollable container.
Also apply .items {min-width: 100%;} in case you want the background to grow full width even with less text in every row.

Is it possible to align my div elements vertically?

I would like to have three separate vertical columns, is there a way I can change my code to make the columns vertical instead of horizontal (like they are now).
.cols {
font-weight: bold;
min-height: 50%;
min-width: 90%;
background: #000000;
margin-bottom: 15px;
display: table;
table-layout: fixed;
}
.cols div {
position: relative;
background: #232323;
}
.col {
display: table-cell;
}
<div class="cols">
<div class="col">Column 1</div>
<div class="col">Column 2</div>
<div class="col">Column 3</div>
</div>
Currently I have three horizontal boxes stretching across an outside container, I would like the three boxes to be evenly set out in vertical columns, if that makes sense.
If I understand what you mean, this can be done using flex:
.cols {
min-height: 50%;
min-width: 90%;
background: #000000;
margin-bottom: 15px;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
.cols div {
background: #232323;
color: #fff;
}
<div class="cols">
<div class="col">Column 1</div>
<div class="col">Column 2</div>
<div class="col">Column 3</div>
</div>