I have an Angular application that has a particular page with a number of rows of data that are generated by *ngFor, these rows look like a table in the sense that each row has similar elements that display a name, description, and have some action buttons. However the data is not stored in a table. The data can also not be stored in a table due to each row being an expansion panel that houses a lot of information within itself and reworking these into a table would probably take too much time.
I need to create a header for this "table", but obviously I can't just do it in the normal way by using table headers. Instead I need to create a separate element that sits above the "table" and has a number of child elements that are positioned in such a way that it gives the impression that it's a header for the series of rows below it.
I've tried doing this in several ways; flexbox, grid, etc but every time I have the same problem with my header. The problem is that when I have the headers aligned properly over the columns if the width of the browser is changed the headers then become unaligned.
I have created a stackblitz to showcase this, here: https://stackblitz.com/edit/angular-ivy-bzazjx?file=src/app/app.component.css
In this example "header 1" should be above "Info" and "header 2" the right-most button. If you adjust the window and make it very big or very small the headers will move around and become misaligned. For example as a very small width "heading 1" will move to be above the left most button. In a similar sense if the browser width is increased the heading will move to the right instead of staying fixed
Is there a way to fix these headers above the elements I want them above such that if the window is changed they will stay fixed above the correct elements and will not displace themselves? I'm all out of ideas as nothing seems to work.
HTML
<div class="test-holder">
<div class="card test-container1">
<h4 class="heading1">Heading 1</h4>
<h4 class="heading2">Heading 2</h4>
</div>
<div class="card d-flex test-container2">
<div class="div1">
<button>Button</button>
</div>
<div class="div1">
<h2>Info</h2>
</div>
<div class="div1">
<h4>More Info</h4>
</div>
<div class="div1">
<p>This is some content</p>
</div>
<div class="div1">
<button>Another button</button>
</div>
</div>
<div class="card d-flex test-container2">
<div class="div1">
<button>Button</button>
</div>
<div class="div1">
<h2>Info</h2>
</div>
<div class="div1">
<h4>More Info</h4>
</div>
<div class="div1">
<p>This is some content</p>
</div>
<div class="div1">
<button>Another button</button>
</div>
</div>
<div class="card d-flex test-container2">
<div class="div1">
<button>Button</button>
</div>
<div class="div1">
<h2>Info</h2>
</div>
<div class="div1">
<h4>More Info</h4>
</div>
<div class="div1">
<p>This is some content</p>
</div>
<div class="div1">
<button>Another button</button>
</div>
</div>
<div class="card d-flex test-container2">
<div class="div1">
<button>Button</button>
</div>
<div class="div1">
<h2>Info</h2>
</div>
<div class="div1">
<h4>More Info</h4>
</div>
<div class="div1">
<p>This is some content</p>
</div>
<div class="div1">
<button>Another button</button>
</div>
</div>
<div class="card d-flex test-container2">
<div class="div1">
<button>Button</button>
</div>
<div class="div1">
<h2>Info</h2>
</div>
<div class="div1">
<h4>More Info</h4>
</div>
<div class="div1">
<p>This is some content</p>
</div>
<div class="div1">
<button>Another button</button>
</div>
</div>
</div>
CSS
.test-holder {
width: 100%;
}
.test-container1 {
width: 100%;
display: flex;
flex-direction: row;
}
.test-container2 {
width: 100%;
flex-direction: row;
justify-content: space-between;
}
.heading1 {
width: 28%;
text-align: right;
}
.heading2 {
width: 68%;
text-align: right;
}
.card {
background-color: #f2f2f2;
}
.d-flex {
display: flex;
}
.div1 {
display: inline-block;
display: flex;
align-items: center;
}
Related
How can I control the middle space between 2 flex items in a row? My goal is to minimize the middle space between the items.
In other words, I want to right and center align the columns, while keeping the text centered.
I would also like to be able to control the middle gutter. Also, maybe be able to say that the middle gutter should be some fixed pixel quantity like 20px.
This doesn't work because there is too much space in the middle
.row {
display: flex;
}
.column {
border: 1px solid #ccc;
width: 50%;
}
h2 {
text-align: center;
}
<div class="row">
<div class="column first">
<h2>Centered</h2>
<h2>Text</h2>
</div>
<div class="column second">
<h2>Centered</h2>
<h2>Text</h2>
</div>
</div>
This don't work because the text in not centered
.row {
display: flex;
}
.column {
border: 1px solid #ccc;
width: 50%;
}
h2 {
text-align: center;
}
.first h2 {
text-align: right;
}
.second h2 {
text-align: left;
}
<div class="row">
<div class="column first">
<h2>Centered</h2>
<h2>Text</h2>
</div>
<div class="column second">
<h2>Centered</h2>
<h2>Text</h2>
</div>
</div>
If you want your elements to have a particular proportion in relation to each other or to the whole (i.e: 50%), flexbox is not even the best solution (although it can be crow-bared to fulfill the requirement).
A simple display: inline-block; width: 50%; box-sizing: border-box on the children will do.
Flexbox was designed to allow fluid distribution of positive or negative space.
As in, after the browser determines how much space the children need and how much they have available, by comparing the two it deals with two cases:
positive space: when parent > sum of children, redistribute the space to each child, proportionally with their respective flex-grow values (until the space is filled) or, if no children have positive flex-grow values, distribute the space in between the children
negative space: if parent < sum of children, shrink each child proportionally with their flex-shrink values.
You have a case of positive space, where the children do not have flex-grow, so the space can be redistributed in between them. You have three options:
justify-content: space-between
justify-content: space-around
justify-content: space-evenly
Notice how the spaces are equally distributed in each case. That's why it's called flexbox, that's what it was designed for and, if you want, that's its superpower.
When you set width: 50% you kind of take all of that away:
.row {
display: flex;
width: 100%;
}
.row>* {
border: 1px solid #ccc;
text-align: center;
}
.one {
justify-content: space-between;
}
.two {
justify-content: space-around;
}
.three {
justify-content: space-evenly;
}
.grow>* {
flex-grow: 1;
margin: 1rem;
}
<code>justify-content: space-between</code>
<div class="row one">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-between (unequal)</code>
<div class="row one">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>justify-content: space-around;</code>
<div class="row two">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-around; (unequal)</code>
<div class="row two">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>justify-content: space-evenly;</code>
<div class="row three">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<code>justify-content: space-evenly; (unequal)</code>
<div class="row three">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>> flex-grow: 1;</code>
<div class="row grow">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<code>> flex-grow: 1; (unequal elements)</code>
<div class="row grow">
<div>
<h2>A bigger element here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
A more detailed explanation on how flexbox works can be found here.
The official spec is here.
Considering your question, there's a big chance justify-content: space-evenly does what you want, but I can't be sure, as your question is not extremely clear.
Important note: You can always use margin and padding on your elements, which will push them around accordingly. Also note margin: auto on flexbox children will steal the positive space from flexbox and will redistribute it equally between all the margin:autos present in parent space (and will make it look like flexbox doesn't work properly; it actually does, but there's nothing left to redistribute).
If you want to have a particular distance in between your elements and the entire composition should be centered in the available space, you could center a single item in the available space and inside that item you could place the items, so that the entire thing is centered regardless of the fact the items are unequal.
Example:
.row {
display: flex;
justify-content: center;
}
.row > * {
margin: 0 auto;
display: flex;
}
.row>*>* {
border: 1px solid #ccc;
text-align: center;
margin: 1rem;
}
<div class="row">
<div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
</div>
<hr>
<div class="row">
<div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
</div>
<hr>
<div class="row">
<div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
</div>
</div>
But, again, that's not something you need flexbox for.
The exact same can be achieved using a simple parent > child structure, where parent has display: block; text-align: center; and children have display: inline-block;
.row {
text-align: center;
}
.row>* {
border: 1px solid #ccc;
text-align: center;
margin: 1rem;
display: inline-block;
}
<div class="row">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<div class="row">
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
</div>
<hr>
<div class="row">
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Centered</h2>
<p>Text</p>
</div>
<div>
<h2>Much more text here</h2>
<p>Text</p>
</div>
</div>
Notice the absence of the extra wrapper in markup.
Why not simply use a CSS grid for the task? It offers the grid-column-gap property which does exactly what you need:
.row {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 10px;
}
.column {
border: 1px solid #ccc;
}
h2 {
text-align: center;
}
<div class="row">
<div class="column">
<h2>Centered<br />Text</h2>
</div>
<div class="column">
<h2>Centered<br />Text</h2>
</div>
</div>
Try doing this
.column:not(:last-child){
margin-left: 20px;
}
I can't get the colors to show up in chrome. I've tried switching the order of the files in <link> just in case that is the problem. I don't see any reason why the colors are'nt showing up in chrome.
.header {
background-color: white;
}
.body {
background-color: blue;
}
<div class="header">
<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="headertext">
<h1> ROBIN HOBB </h1>
</div>
</div>
<div class="col-md-4">
<div class="facebookbuttons"></div>
<div class="fantasy_text"></div>
</div>
</div>
</div>
</div>
<div class="body">
<div class="container"></div>
</div>
Your .body class DIV doesn't have any content. If you put some text into it, you see the blue background:
(and since the browser windows background is white by default, you won't see the white background on your .header DIV...)
.header {
background-color: white;
}
.body {
background-color: blue;
}
<div class="header">
<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="headertext">
<h1> ROBIN HOBB </h1>
</div>
</div>
<div class="col-md-4">
<div class="facebookbuttons"></div>
<div class="fantasy_text"></div>
</div>
</div>
</div>
</div>
<div class="body">
<div class="container">Here is some content</div>
</div>
.header {
background-color: white;
}
body {
background-color: blue;
}
<div class="header">
<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="headertext">
<h1> ROBIN HOBB </h1>
</div>
</div>
<div class="col-md-4">
<div class="facebookbuttons"></div>
<div class="fantasy_text"></div>
</div>
</div>
</div>
</div>
<div class="body">
<div class="container"></div>
</div>
I assume you are trying to change the entire page background color which needs to be done with a body { ... } selector not .body{ ... } as in this sample.
However, if the goal is to target the with a class of body your CSS is correct but there is nothing inside for content so it has a height of 0 by default. Add content like Johannes mentioned and it should work for you.
I know this may be easy for most of you but I'm stuck with this issue.
I need to implement this design:
Layout Design
... and for now I've got this Current layout.The general structure is a row with col-3 and col-9, this col-9 has two rows, one for name and job title, and the other one for statistics in the page (col-3 for each of them). I need them to fill the height of his parent, but height property doesn't work. Which could be a clean solution? Thanks a lot.
Here is the structure, it's pretty simple tho.
<div class="row profile-header">
<div class="col-md-3 user-image text-center">
<img ...>
<span>..</span>
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-12">
<h2 class="text-white">...</h2>
<h4 class="text-muted">...</h4>
</div>
</div>
<div class="row text-center">
<div class="col-md-3 stat">
<h3>...</h3>
<small>...</small>
</div>
...
</div>
</div>
Use position: relative on the parent and then position:absolute; bottom: 0; on the children.
Nice explanation there.
Flexbox would be my recommendation although CSS tables might be an option too.
Codepen Demo
Snippet Demo (view Fullscreen)
.user-image {
background: pink;
}
.user-image img {
display: block;
margin: auto;
}
.profile-header {
display: flex;
}
.right {
background: #c0ffee;
display: flex;
flex-direction: column;
}
.stats {
margin-top: auto;
}
.stat {
background: lightgrey;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="row profile-header">
<div class="col-md-3 user-image text-center">
<img src="http://www.fillmurray.com/300/200" alt="" />
<span>User Ranking</span>
</div>
<div class="col-md-9 right">
<div class="row">
<div class="col-md-12">
<h2 class="text-white">User Name</h2>
<h4 class="text-muted">reference</h4>
</div>
</div>
<div class="row text-center stats">
<div class="col-md-3 stat">
<h3>Some Stat</h3>
<small>Some Stat</small>
</div>
<div class="col-md-3 stat">
<h3>Some Stat</h3>
<small>Some Stat</small>
</div>
<div class="col-md-3 stat">
<h3>Some Stat</h3>
<small>Some Stat</small>
</div>
<div class="col-md-3 stat">
<h3>Some Stat</h3>
<small>Some Stat</small>
</div>
</div>
</div>
im kind of new to css/html and bootstrap itself. I've encountered two problems.
One is: I want to fix the 3rd and 4th box height to 100%, but no mater what div, or class i change to 100% it makes no changes.
Second: How can i make Box4 go under box2, so its not inline with box3?
Link to describe problem: http://jsfiddle.net/BXZrX/6/
and here is a picture of what i want: http://oi62.tinypic.com/osqule.jpg
<div id="content">
<div class="jumbotron">
<div class="container-fluid">
<h1>Join now!</h1>
<p>To get full use of the website, register now!.</p>
Sign up
</div>
</div>
<div class="bordertop">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box2</h1>
<p>text</p>
</div>
</div>
</div>
<div class="box3">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box3</h1>
<p>text</p>
</div>
</div>
</div>
<div class="box4">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box4</h1>
<p>text</p>
</div>
</div>
</div>
</div>
#content > div {
float:left;
width:49%;
}
#content > div.bordertop {
float:right;
width:49%;
}
#content > div.box3 {
clear:both;
width:49%;
float:left;
}
#content > div.box4 {
float:right;
width:49%;
}
Here's a start:
http://jsfiddle.net/jPZLd/11/
I've swapped boxes 2 and 3 so that they flow correctly down then across the page:
<div id="content">
<div class="column">
<div class="jumbotron">
<div class="container-fluid">
<h1>Join now!</h1>
<p>To get full use of the website, register now!.</p>
Sign up
</div>
</div>
<div class="bordertop">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box2</h1>
<p>text</p>
</div>
</div>
</div>
</div>
<div class="column">
<div class="box3">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box3</h1>
<p>text</p>
</div>
</div>
</div>
<div class="box4">
<div class="jumbotron">
<div class="container-fluid">
<h1>Box4</h1>
<p>text</p>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
Footer
</div>
If you need both boxes 2 and 4 to have the same baseline, it's easy if your content is static - just adjust the height of the shorter box manually, eg.
.box4 .jumbotron {
height: 319px;
}
It gets a bit harder if you have to deal with dynamic content. I think you'd end up needing to fake it by applying the background color to the container element and hiding the bits you don't want to see.
I am trying to display dynamic generated div's horizontally with scroll bar. There can be n number of div's.
Below is my Code:
HTML (index.html)
<div style="width:100%;float:left;" id="old">
<div>
<h1>First Div</h1>
<div id="R1">
<h1>First Div Internal</h1>
<a id="R1_index" class="close_page" href="javascript:void(0)">Close</a>
</div>
</div>
<div>
<h1>Second Div</h1>
<div id="R2">
<h1>Second Div Internal</h1>
<a id="R2_index" class="close_page" href="javascript:void(0)">Close</a>
</div>
</div>
</div>
I follow this link for solution.
But when dynamic div's load, structure looked messed up.
Here is the messy look:
HTML (index.html)
<div style="width:100%;float:left;" id="old">
<div id="items">Missing Internal Content</div>
<div id="items">Missing Internal Content</div>
</div>
Please help me guys.
i imagin the problem is that the div's in the container (id="old" in your example) are not next to each other, but instead beneath.
if that is your problem, you add the following styles to your container:
#old {
overflow: auto;
white-space: nowrap;
}
and make the childern-divs inline-block elements:
#old > div {
display: inline-block;
}
then it should work as expected. see the working solution:
* {
padding: 0;
margin:0;
}
#container {
width: 300px;
height: 100px;
overflow: auto;
white-space: nowrap;
}
.element {
display: inline-block;
}
.box {
width: 100px;
height: 100px;
background: lightgrey;
}
<div id="container">
<div class="element">
<div class="box">
<h1>1</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>2</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>3</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>4</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>5</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>6</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>7</h1>
</div>
</div>
<div class="element">
<div class="box">
<h1>8</h1>
</div>
</div>
</div>
otherwise please provide a better example/description of what the problem exactly is.