I am using Angular 6 and my templates are as below.
Header, Left panel, Body part, footer
Header,Left panel, Body part, right panel, footer
Header, body part, footer
Since, I have so many templates, I wanted to make it JSON driven instead of just hardcoding html part.
The JSON file will look like,
{
"horizontal" : [
{
width : 20%,
height: 100%
},
{
width : 80%,
height: 100%,
{
"vertical" : [
{
width : 80%,
height: 60%
},
{
width : 80%,
height: 40%
}
]
}
}
],
}
Here, the page gets divided into left panel(20% width) and body(80%) and then body gets divided into vertically like 60% top and 20% bottom.
Is there any way to make this JSON into HTML?
While this question is too broad, I were/am a back end guy too, and wen't through many ideas before landing, so I decided to post an answer and share my experience.
My intention with this is to show how simple, and with how little code, one can create something reusable and easy to maintain.
Instead of convert styles from a JSON to HTML, use what is meant for that, CSS, and here is a few samples how to manage many templates with a small style guide, and get one of the best features of all, performance.
With one CSS, making using Flexbox, and the given logic for your different templates, it could look like this.
Sample 1 (with CSS notes)
html, body, .container {
height: 100%;
margin: 0;
}
.container, main {
display: flex; /* make children flex items */
flex-direction: column; /* default flow is row */
}
header, footer { /* flex column item will by default fill parent's width */
/* height is controlled by content */
}
.wrapper {
flex: 1; /* fill remaining height (flex column item) */
display: flex;
}
aside { /* flex row item will by default fill parent's height */
flex-basis: 20%; /* set width (flex column item) */
}
main {
flex: 1; /* fill remaining width (flex row item) */
}
section {
flex-basis: 60%; /* set height (flex column item) */
}
section + section { /* target the 2nd section */
flex-basis: 40%;
}
/* for demo purpose */
header, footer, aside, section {
border: 1px dotted gray;
}
<div class="container">
<header>Header</header>
<div class="wrapper">
<aside>Aside</aside>
<main>
<section>Section</section>
<section>Section</section>
</main>
</div>
<footer>Footer</footer>
</div>
Sample 2
html, body, .container {
height: 100%;
margin: 0;
}
.container, main {
display: flex;
flex-direction: column;
}
header, footer {
}
.wrapper {
flex: 1;
display: flex;
}
aside {
flex-basis: 20%;
}
main {
flex: 1;
}
section {
flex-basis: 60%;
}
section + section {
flex-basis: 40%;
}
header, footer, aside, section {
border: 1px dotted gray;
}
<div class="container">
<header>Header</header>
<div class="wrapper">
<aside>Aside</aside>
<main>
<section>Section</section>
<section>Section</section>
</main>
<aside>Aside</aside>
</div>
<footer>Footer</footer>
</div>
Sample 3
html, body, .container {
height: 100%;
margin: 0;
}
.container, main {
display: flex;
flex-direction: column;
}
header, footer {
}
.wrapper {
flex: 1;
display: flex;
}
aside {
flex-basis: 20%;
}
main {
flex: 1;
}
section {
flex-basis: 60%;
}
section + section {
flex-basis: 40%;
}
header, footer, aside, section {
border: 1px dotted gray;
}
<div class="container">
<header>Header</header>
<main>
<section>Section</section>
<section>Section</section>
</main>
<footer>Footer</footer>
</div>
Or for a given template, using different CSS (only show 1 and 3 here, as 2 will be the same as the above)
Sample 1
html, body, .container {
height: 100%;
margin: 0;
}
.container, main {
display: flex;
flex-direction: column;
}
header, footer {
}
.wrapper {
flex: 1;
display: flex;
}
aside {
flex-basis: 20%;
}
main + aside { /* target the 2nd/right aside */
display: none;
}
main {
flex: 1;
}
section {
flex-basis: 60%;
}
section + section {
flex-basis: 40%;
}
/* for demo purpose */
header, footer, aside, section {
border: 1px dotted gray;
}
<div class="container">
<header>Header</header>
<div class="wrapper">
<aside>Aside</aside>
<main>
<section>Section</section>
<section>Section</section>
</main>
<aside>Aside</aside>
</div>
<footer>Footer</footer>
</div>
Sample 3
html, body, .container {
height: 100%;
margin: 0;
}
.container, main {
display: flex;
flex-direction: column;
}
header, footer {
}
.wrapper {
flex: 1;
display: flex;
}
aside {
display: none;
}
main {
flex: 1;
}
section {
flex-basis: 60%;
}
section + section {
flex-basis: 40%;
}
/* for demo purpose */
header, footer, aside, section {
border: 1px dotted gray;
}
<div class="container">
<header>Header</header>
<div class="wrapper">
<aside>Aside</aside>
<main>
<section>Section</section>
<section>Section</section>
</main>
<aside>Aside</aside>
</div>
<footer>Footer</footer>
</div>
Related
I am having issues trying to make my footer at the bottom, but it overlaps the content on the page if there are too much content.
this is my footer css
footer {
position:fixed;
bottom: 0;
}
this is how the page looks without any content
this is how the page looks with overlap content with the footer
You could structure your HTML as follows:
<body>
<header class="Header"></header>
<main class="Main"></main>
<footer class="Footer"></footer>
</body>
Then, use flex box to render the footer at the bottom of your page using the following code:
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
footer,
header {
flex: 0;
}
See a fully working demo code below and learn more about flex box here:
header::after,
main::after,
footer::after {
content: attr(class);
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
margin: 0;
}
main {
flex: 1;
}
footer,
header {
flex: 0;
}
<header class="Header"></header>
<main class="Main"></main>
<footer class="Footer"></footer>
Attaching a page layout to explain my requirements better.
Place the the text just before the footer section.
Some time the footer may not be visible (may need scroll), in that case bring the text to the bottom of visible area.
I have tried many ways to achieve this.
Any pointers to solve this issue would be helpful.
Thanks,
Santhosh
You can use flexbox to achieve this
body {
margin: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
/* occupy all height */
flex: 1 0 auto;
/* nested flex container */
display: flex;
flex-direction: column;
}
.bottom-text {
/* Move to the bottom */
/* This works because this is flex item */
margin-top: auto;
}
/* styles just for demo */
body {
text-align: center;
}
header {
background-color: tomato;
}
.content {
background-color: lightsteelblue;
}
.bottom-text {
background-color: moccasin;
}
footer {
background-color: lime;
}
<header>Page header</header>
<section class="content">
Page content
<div class="bottom-text">Place a text just before footer</div>
</section>
<footer>Page footer</footer>
For showing bottom-text when footer is not visible we'll use Javascript:
// Checks if element is visible on screen
function checkVisible(element) {
var rect = element.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}
var footer = document.querySelector("footer");
var bottomText = document.querySelector(".bottom-text");
var bottomTextFixedClassName = "bottom-text--fixed";
// Sets element position as fixed
// when footer is not visible on screen
function setFixedButtonText() {
if (checkVisible(footer))
bottomText.classList.remove(bottomTextFixedClassName);
else
bottomText.classList.add(bottomTextFixedClassName);
}
window.addEventListener("scroll", setFixedButtonText);
setFixedButtonText();
body {
margin: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
/* occupy all height by flex-grow: 1 */
/* Don't shrink using flex-shrink: 0 */
/* Setting flex-basis to 1500px to emulate long content */
/* Replace 1500px with auto in production code */
flex: 1 0 1500px;
/* nested flex container */
display: flex;
flex-direction: column;
}
.bottom-text {
/* Move to the bottom */
/* This works because this is flex item */
margin-top: auto;
}
.bottom-text--fixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
}
/* styles just for demo */
body {
text-align: center;
}
header {
background-color: tomato;
}
.content {
background-color: lightsteelblue;
}
.bottom-text {
background-color: moccasin;
}
footer {
background-color: lime;
}
<header>Page header</header>
<section class="content">
Page content
<div class="bottom-text">Place a text just before footer</div>
</section>
<footer>Page footer</footer>
If you need IE suppost you can use change min-height: 100vh; to height: 100vh;. This is workaround for IE's min-height bug for flex with flex-direction: column;.
I'm attempting to learn flexbox and I'm trying to achieve the following layout.
+----------+----------+
| |nav |
| header +----------+
| |section |
+----------+----------+
HTML Structure
<header></header>
<nav></nav>
<section></section>
Layout Requirements
Width of each element is exactly 50vw (or 50%)
Header content is always centered and fixed. Takes up 100vh.
Nav content is fixed
Section content is scrollable, overflow is hidden.
Is this even possible with flexbox?
On mobile devices, I want to have all three in a column but that part is easy.
body {
display: flex;
flex-flow: column wrap;
height: 100vh; /* key rule; this tells flex items where to wrap
to form second column */
}
header {
flex: 0 0 100%;
width: 50%;
/* center content */
display: flex;
justify-content: center;
align-items: center;
}
nav, section {
flex: 0 0 50%;
width: 50%;
}
/* non-essential decorative styles */
* { box-sizing: border-box; margin: 0; }
header { background-color: aqua; }
nav { background-color: tomato; }
section { background-color: lightgreen; }
<header>header</header>
<nav>nav</nav>
<section>section</section>
For a detailed explanation and alternative methods see my answer here:
Is it possible for flex items to align tightly to the items above them?
if you want to use flexbox you can get away with doing a dual container layout.
HTML
<div class="flex-container">
<header>Something</header>
<div class="flex-child-container">
<nav>nav</nav>
<section>section</section>
</div>
</div>
CSS
div {
display: flex;
width: 100%;
height: 100%
}
.flex-child-container {
flex-direction: column;
}
I'd like to know: is it possible to build a 3 rows layout, 100% height, with flexbox?
<header> The header content goes here. </header>
<div class="content"> The main content goes here. </div>
<footer> The footer content goes here. </footer>
fixed-height header and footer, while content the liquid part.
I mean, something like this but without absolute positioning:
* {
margin: 0;
}
header {
position: absolute;
width: 100%;
height: 64px;
top: 0;
background: red;
}
footer {
position: absolute;
width: 100%;
height: 64px;
bottom: 0;
background: green;
}
.content {
position: absolute;
width: 100%;
top: 64px;
bottom: 64px;
background: blue;
}
<header>The header content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer content goes here.</footer>
http://jsfiddle.net/BMxzn/
body {
display: flex;
flex-direction: column;
height: 100vh;
}
.content {
flex: 1; /* this is the key; consumes all available height */
background: blue;
}
header {
height: 64px;
background: red;
}
footer {
height: 64px;
background: green;
}
* {
margin: 0;
}
<header>The header content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer content goes here.</footer>
I add my own accepted answer here, because it addresses other issues as well.
I noted that the usually suggested code has a problem with Android prior to 4.4.4. By better indagating > this and > this I found out that the problem is > this, even if Android is not mentioned on the affected browsers list. So, my solution was to add flex-shrink: 0 to the content:
body{
display: flex;
flex-direction: column;
height: 100%;
}
.main-content{
flex: 1 0 auto; // flex-shrink:0 > android 4.4.2 fix (and some other browsers too)
}
It's also good to assign some kind of flex property to header and footer. I noticed on Android 442 that otherwise the bg color was gone:
.main-header,
.main-footer{
flex: none; // or flex something.
}
Also please note that I'm using Autoprefixer. Otherwise, you should not use the shortcut on main-content (IE shit-fix):
.main-content{
flex-grow: 1;
flex-shrink:0;
flex-basis:auto;
}
Very similar to these question : this & this
You need only 3 lines of code:
display:flex;
flex-flow:column;
height:/* whatever height needed */
and then flex:1; to the container that needs to fill remaining space
* {
margin: 0;
}
body {
display: flex;
flex-flow: column;
height: 100vh;/* if you relay on flex, then vh is also understood */
}
body>* {
padding: 1em;
}
header {
background: red;
}
footer {
background: green;
}
.content {
flex: 1;
background: blue;
color: white;
/* optionnal if you want to keep footer at screen
overflow:auto; */
}
<header>The header <b>of any height</b> content goes here.</header>
<div class="content">The main content goes here.</div>
<footer>The footer <b>of any height</b> content goes here.</footer>
there is no need to set heights to footer or header , but you might add overflow:auto to the main container.
As an example, I've made a fiddle:
https://jsfiddle.net/L7mwpzux/3/
How do I make the div .container minimally fill the screen?
So when there is almost no content, it still fills the screen.
It's for a page that is shown when the checkout cart is empty. The content is too thin, so the screen is not fully filled with content.
P.s. I am not looking for an answer that assumes that the header or footer has a static height. I want to be able to use it also in situations where the height of the header or footer is variable.
Also, I would love a CSS solution, so no JavaScript or jQuery
You can use calc() and set 100vh - height of header, also add box-sizing: border-box to keep padding inside.
* {
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
}
header {
height: 200px;
background-color: blue;
width: 100%;
}
.container {
padding: 50px;
min-height: calc(100vh - 200px);
}
footer {
width: 100%;
height: 200px;
background-color: #333;
}
<header>
</header>
<div class="container">
small text
</div>
<footer>
</footer>
Other approach is to use Flexbox and set display: flex on body which is parent element in this case with min-height: 100vh and then just set flex: 1 on .container so it takes rest of free height.
* {
box-sizing: border-box;
}
body,
html {
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
header {
height: 100px;
background-color: blue;
}
.container {
padding: 50px;
flex: 1;
}
footer {
height: 100px;
background-color: #333;
}
<header>
</header>
<div class="container">
small text
</div>
<footer>
</footer>
try this
min-height: calc(100vh - 400px);
here is the fiddle https://jsfiddle.net/L7mwpzux/1/