Using a media query with viewheight to fix footer - javascript

I am trying to create my own website with a basic structure (header, main and footer) but when there are not enough elements to fill the height of the screen, footer is not placed at the bottom.
To fix that problem I used these lines:
footer {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
but now that there are enough elements and should be scroll, the footer still fixed (what is obvious) so I am trying to create a media query to change footer's css when the height of the body is larger than 100vh - and it is not working and I do not know why. How can I fix it?
#media screen and (min-width: 100vh) {
footer {
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
}
}
I know that I could choose any of them depending on the final structure but meanwhile I would like to forget about having to change the footer's css manually.
Thank you in advance.

I understand what you need to make and I offer you to use flex on container.
<div class="container">
<header></header>
<main></main>
<footer></footer>
</div>
If you use this structure, add below styles then you will never need to add position fixed and media query to footer.
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}

To make <body> fill the whole page vertically:
html {
height: 100% /*of viewport's height*/;
}
body {
/* At least 100%;
* allows vertical scrollbars if content overflows
*/
min-height: 100%;
/* Reset margin:
* Margins don't count towards size.
* If wanted, you'd need to explicitly subtract
* them from size declarations.
*/
margin: 0;
}
To distribute <body>'s space, you can use CSS Grid:
body {
display: grid;
grid-template-rows:
auto /*First row: Take up required space*/
1fr /*Middle row: Take up remaining space, after required space is allotted*/
auto /*Last row: Take up required space*/;
}
/*Previous rules*/
html {height: 100%}
body {
margin: 0;
min-height: 100%;
}
/*Ignore; for presentational purposes*/
header, main, footer {
min-height: 4rem;
}
header {background-color: cornflowerblue}
main {background-color: brown}
footer {background-color: darkkhaki}
<html>
<body>
<header></header>
<main></main>
<footer></footer>
</body>
</html>

just write a property for the parent element of the entire site:
min-height: 100%;
and for the section before the footer, you need to register the following property:
flex-grow: 1;
Its default value for 'flex' is 0 1 auto , which means. flex-grow: 0; flex-shrink: 1; flex-basis: auto;

Related

Making gallery responsive with css

I am trying to build simple gallery.
What I would like to achieve is this:
However, what I am actually achieving is this:
There is basically too much space between images and I can't find a way how to solve it. I understand that is because of justify-content: space-between; but perhaps there's another option that will put less space between the images?
Html
<div class="photoContainer>
<div class="ant-image">
...
</div>
</div>
Css
.photosContainer {
width: 80%;
height: 100%;
overflow: auto;
overflow-x: hidden;
display: flex;
align-content: space-between;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
padding: 10px;
}
.ant-image {
height: fit-content;
flex-shrink: 0;
position: relative;
display: inline-block;
width: 200px;
}
With the space-between rule you cannot have the control of the space between the images.
My suggestion is to:
make the image gallery container smaller because you have a small number of photos
to have more control over the images you can use also for the single image a % width as you have done for the container.
hint: use property object-fit for the single images
you can use grid display instead of flex and solve your problem:
.photosContainer{
display:grid;
grid-template-columns:repeat(4 , 1fr);
}

Flexbox columns with auto vertical scrollbar on container does not fill entire screen to 100% [duplicate]

If the total content height of the parent is 10,000px but the overflow: auto element is rendered with a height of 700px how do I force the aside child element to dynamically render as 10,000px instead of the default 700px? You can see the white background the moment you begin to scroll the Fiddle.
May not add any more elements (::after and ::before are acceptable though).
The aside element must have it's content scroll with main element's content via the #body element (no position: fixed;).
The aside element must have it's background-color stretch from the very top at 0px to the very bottom (e.g. 5,000px or 10,000px) far below the initial visible fold.
The aside element must not have it's own overflow: auto;.
Dynamic (for the lesser knowledged) implies we can not set a static height, e.g. height: 10000px as we will not know what the rendered height will be.
In my example the moment you begin to scroll the green background-color ends, I want to make the aside element stretch all the way to the content bottom.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Overflow Flex Box Issue</title>
<style type="text/css">
* {border: 0; margin: 0; padding: 0;}
aside
{
background-color: #afa;
order: 2;
width: 20%;
}
body
{
display: flex;
flex-direction: column;
height: 100%;
}
body > header
{
align-self: stretch;
background-color: #faa;
flex: 0 1 auto;
min-height: 56px;
order: 1;
}
body > footer
{
align-self: auto;
background-color: #aaf;
flex: 0 1 auto;
min-height: 36px;
order: 2;
}
html {height: 100%;}
main
{
background-color: #cfc;
order: 1;
width: 80%;
}
#body
{
display: flex;
order: 2;
overflow: auto;
}
</style>
</head>
<body>
<div id="body">
<main>
<article>
<p>article</p>
<p>article</p>
<p>article</p>
<div style="height: 10000px;">10,000px</div>
</article>
</main>
<aside><p><aside>, 100% height only of visible area, it <em>should</em> be <em>100% of total parent height</em>.</p></aside>
</div>
<header>The body > header element; element 2, order: 1;.</header>
<footer>The body > footer element; element 3, order: 3;.</footer>
</body>
</html>
Barring absolute positioning, this is not possible with CSS. You'll need to use JavaScript.
Here's the problem:
Part I: background-color
You have no height defined for the content element (#body).
This means that the height is content-driven.
A background color will only cover the width and height of the element. You can see this in your demo. As soon as the scrolling begins, the background color ends. That's because the overflow area is outside the width / height area of the element.
From the spec:
14.2 The
background
Authors may specify the background of an element (i.e., its rendering
surface) as either a color or an image. In terms of the box
model, "background"
refers to the background of the content, padding and border
areas.
So CSS background properties are designed to cover an area up to the borders of the element. They do not cover the margin area. They do not overflow.
Part II: overflow
This is another reason for the truncated background color.
The overflow property only applies to content. It has nothing to do with backgrounds.
From the spec:
11.1.1 Overflow: the overflow
property
This property specifies whether content of a block container element
is clipped when it overflows the element's box.
With these two obstacles standing in the way, CSS is not useful in solving this problem (except for possible hacks). The only way to make a background color fill the entire length of a dynamically-sized container would be with a script.
Not sure if this meets all of your criteria, but how about this solution? Simply wrapping the parent div in a container and setting the overflow-y to auto like so should do the trick:
.container {
overflow-y: auto;
}
This is not the way I intended to achieve the result as I would like to set background-image on the #body in many cases though it may be acceptable subjective to how I handle things, here is the Fiddle. I'm certain that this issue will be resolved at some point in the future.
#body
{
background-image: linear-gradient(to right, #cfc 0%, #cfc 79%, #afa calc(79% + 4px), #afa 100%);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Overflow Flexbox Issue</title>
<style type="text/css">
* {border: 0; margin: 0; padding: 0; scroll-behavior: smooth;}
aside
{
background-color: ;
order: 2;
width: 20%;
}
body
{
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
body > header
{
align-self: stretch;
background-color: #faa;
flex: 0 1 auto;
min-height: 56px;
order: 1;
}
body > footer
{
align-self: auto;
background-color: #aaf;
flex: 0 1 auto;
min-height: 36px;
order: 2;
}
html {height: 100%;}
main
{
order: 1;
width: 80%;
}
#body
{
background-image: linear-gradient(to right, #cfc 0%, #cfc 79%, #afa calc(79% + 4px), #afa 100%);
display: flex;
order: 2;
overflow: auto;
}
</style>
</head>
<body>
<div id="body">
<main>
<article>
<p>article</p>
<p>article</p>
<p>article</p>
<div style="height: 10000px;">10,000px</div>
</article>
</main>
<aside><p><aside>, 100% height only of visible area, it <em>should</em> be <em>100% of total parent height</em>.</p></aside>
</div>
<header>The body > header element; element 2, order: 1;.</header>
<footer>The body > footer element; element 3, order: 3;.</footer>
</body>
</html>
Actually, there's a pretty simple solution with just CSS and without touching the markup.
display:table-cell for the aside and the main
omit the display flex on the #body
Here's a fully functional snippet:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Overflow Flex Box Issue</title>
<style type="text/css">
* {border: 0; margin: 0; padding: 0;}
aside
{
background-color: #afa;
order: 2;
width: 20%;
display: table-cell;
}
body
{
display: flex;
flex-direction: column;
height: 100%;
}
body > header
{
align-self: stretch;
background-color: #faa;
flex: 0 1 auto;
min-height: 56px;
order: 1;
}
body > footer
{
align-self: auto;
background-color: #aaf;
flex: 0 1 auto;
min-height: 36px;
order: 2;
}
html {height: 100%;}
main
{
background-color: #cfc;
order: 1;
width: 80%;
display: table-cell;
}
#body
{
order: 2;
overflow: auto;
}
</style>
</head>
<body>
<div id="body">
<main>
<article>
<p>article</p>
<p>article</p>
<p>article</p>
<div style="height: 10000px;">10,000px</div>
</article>
</main>
<aside><p><aside>, 100% height only of visible area, it <em>should</em> be <em>100% of total parent height</em>.</p></aside>
</div>
<header>The body > header element; element 2, order: 1;.</header>
<footer>The body > footer element; element 3, order: 3;.</footer>
</body>
</html>

Increase the height of all elements when one element increases (equal height columns)

I want all 100% height elements to expand when the size of the body expands.
In the example pressing the button will add a red div - the two columns adjacent should stretch to account for this. In the end all columns should reach the bottom completely, one with blue then red, the other two just blue.
I'm looking into flex, and it doesn't seem like this would work, but any suggestions are appreciated.
In any case best solution is CSS, but if this is impossible pure JS is also fine.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
}
span {
display: inline-block;
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
This is what I expect the frame to look like at the bottom after button is pressed and scrolled down:
EDIT
I changed the snippet so the button appends the div to an existing child and causes overflow, as per the comments below suggest.
An initial setting of a flex container is align-items: stretch. This means that flex items will expand to cover the full length of the container along the cross axis.
In a container with flex-direction: row, the cross axis is vertical, so items will expand to full height.
In your demo code, the divs (red) are being added as children of a span column (blue). These divs are being added to the end, forcing the column to grow.
In a row-direction flex container, with no heights specified that would override align-items: stretch, the other columns will follow suit.
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
body {
display: flex;
min-height: 100vh;
}
body > span {
width: 30px;
margin-right: 5px;
background-color: blue;
display: flex;
flex-direction: column;
}
body > span:first-child span {
flex: 0 0 100vh;
}
div {
background-color: red;
width: 30px;
height: 30px;
}
button {
margin-bottom: auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>
You should use Flexbox twice, once in the outer container, and once in the container containing the appended child elements.
Here is your modified code:
span = document.getElementsByTagName("span")[0];
function addelem() {
span.appendChild(document.createElement('div'));
};
html, body{
height: 100%;
/* new */
display: flex;
}
/* new */
body > span{margin-right: 4px;}
span {
/*display: inline-block;*/
background-color: blue;
width: 30px;
height: 100%;
vertical-align: top;
/* new */
display: flex;
flex-flow: column;
align-items: flex-end;
}
div {
background-color: red;
width: 30px;
height: 30px;
/* new */
flex: 1 0 auto;
}
<span><span></span></span>
<span></span>
<span><button onclick="return addelem()">+</button></span>

Remove a class when two divs overlap

I have used flexbox to center my content vertically inside of 'main' tag, however when too much content is added it spills over into the 'header'. Is there a way I can calculate that if the div goes above a certain vertical position on screen (256px - height set as header), it removes a class from the 'main' (currently set to .vertical).
I know that the .removeClass() removes the class, but I dont know where to start with the vertical position calculation.
HTML
<header>Nav</header>
<main class="vertical">A lot of text here</main>
CSS
body, html{margin:0; height:100%}
header{width:100%; height:256px; background:red;}
main{width:100%; height: calc(100% - 256px); background:#fff;}
.vertical{
display: flex;
flex-direction: column;
justify-content: center;
}
Fiddle
I do hope that makes sense.
Many thanks Thanks.
I may misunderstand your goal, but it doesn't seem like you need to calculate the position on the screen. Since you have a Nav bar, it should always be visible and the content shouldn't overlap. I made a few changes to your code that allows the content to always sit underneath the header using justify-content: flex-start.
body, html {
margin: 0;
height: 100%
}
header {
display: block;
width: 100%;
height: 256px;
background: red;
}
main {
width: 100%;
height: 100%;
background: #fff;
}
.vertical{
display: flex;
flex-direction: column;
justify-content: flex-start;
}
If you still want to align the text differently, you could nest the content within another tag inside .vertical. Like so:
<header>Nav</header>
<main class="vertical">
<p class="content">all the text...</p>
</main>
And then add vertical styles to the .content section.

Using CSS display:flex (flexbox) and/or JavaScript to make adjustable page

I'm making a simple IDE for a educational programming language similar to Karel the Dog. And I have trouble with making base html page.
I have 4 areas:
Toolbox (for buttons like open, save as, run etc.)
Field (canvas for drawing executor that can move on the field and do some stuff)
Code (CodeMirror editor for writing executor's commands)
Console (place where IDE can print messages like compilation errors or runtime debug output)
I wrote what I want from every area in my code so I'll say only what is not working now:
The page should fill 100% screen's height.
Cannot set CodeMirror to fill all available to its parent height. And when its size is greater than parent's height, scrollbars should appear.
The same problem with canvas - but only on vertical.
Is there a way to make a separator between code and field areas that can be used to redistribute horizontal space between areas?
There is another difficulty. If the item number 4 requires JavaScript, then I'll ask to help me with solving it with WinJS 3.0 library because I won't add to the project jQuery or other heavy stuff only for this resize capability.
So, can anyone help me?
I loaded my code to jsfiddle.net and pasted it here:
var ce = CodeMirror(document.getElementById('b-codemirror'), {
value: "\n\n\nIt is CodeMirror element. [PARAMS ALL] " +
"width: 100% of parent element, height: always 100% of" +
" parent element + both scrollbars if needed\n\n\n",
lineNumbers: true
});
var cc = document.getElementById("canvas").getContext("2d");
cc.font = "16px Helvetica";
cc.fillText("It is canvas. Can be resized from", 10, 30);
cc.fillText("JS. If it is larger than parent element,", 10, 60);
cc.fillText("corresponding scrollbar should appear.", 10, 90);
#import url("http://codemirror.net/lib/codemirror.css");
/* overriding default codemirror.css */
.CodeMirror {
font-family: monospace;
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.b-section {
margin: 2px;
padding: 4px;
border-radius: 4px;
}
#b-fieldcode {
min-height: 640px;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row;
flex-flow: row;
}
#b-toolbox {
background: #ffeebb;
}
#b-console {
height: 100px;
background: #ffeebb;
}
#b-field {
background: #ccccff;
overflow: auto;
-webkit-flex: 1 1 40%;
flex: 1 1 40%;
-webkit-order: 1;
order: 1;
}
#b-code {
background: #dddd88;
-webkit-flex: 1 1 60%;
flex: 1 1 60%;
-webkit-order: 2;
order: 2;
}
#media all and (max-width: 1024px) {
#b-fieldcode, #page {
-webkit-flex-flow: column;
flex-flow: column;
flex-direction: column;
}
#b-code, #b-field {
-webkit-order: 0;
order: 0;
}
#b-field, #b-code {
height: 500px;
}
}
<script type="text/javascript" src="http://codemirror.net/lib/codemirror.js"></script>
<div id="b-toolbox" class="b-section">
Here comes the space for buttons.
[PARAMS ALL] width: 100% of screen, height: sized to content
</div>
<div id="b-fieldcode">
<div id="b-field" class="b-section">
Here comes canvas wrapper.<br />
[PARAMS landscape] width: flex 40% of screen, height:
100% of screen minus b-toolbox and b-console.
<br />[PARAMS portrait] width: 100% of
screen, height: fixed 400px.<br />
<canvas width="300" height="300" id="canvas"
style="background-color: green" />
</div>
<div id="b-code" class="b-section">
Here comes CodeEditor wrapper.<br />
[PARAMS landscape] width: flex 60% of screen, height:
100% of screen minus b-toolbox and b-console.<br />
[PARAMS portrait] width: 100% of
screen, height: fixed 500px.
<div id="b-codemirror"></div>
</div>
</div>
<div id="b-console" class="b-section">
Here comes output console.
[PARAMS ALL] width: 100% of screen, height: fixed 120px.
</div>
First of all, you need to split styles for portrait and landscape. For portrait part, that's simple easy, so let's skip it.
For landspace part, you need a fluid height header (buttons) and a fixed height footer (console). This is a typical use case of css flex - all spare space are going to main part. So you just set display: flex; flex-direction: column; to <body> and flex: 1; to the main part (#fieldcode in your snippet).
Then #field occupies 40% width of #fieldcode, and #code ocuppies 60%. So again, you set display: flex; flex-direction: row; to #fieldcode, and flex: 4; to #field, flex: 6; to #code, so that spare space of #fieldcode is separated as 4:6. But please note the difference from previous. Yes, the flex-direction value is different. That tells the browser either to separate horizontally, or vertically.
html, body {
margin: 0;
padding: 0;
}
#toolbox {
background: #feb;
}
#field {
background: #ccf;
overflow: auto;
}
#code {
background: #dd8;
overflow: auto;
}
#codemirror {
min-width: 100%;
min-height: 100%;
}
#console {
background: #feb;
height: 120px;
}
#media screen and (orientation: portrait) {
#field {
height: 400px;
}
#code {
height: 500px;
}
}
#media screen and (orientation: landscape) {
html, body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
}
#fieldcode {
flex: 1;
display: flex;
flex-direction: row;
}
#field {
flex: 4;
}
#code {
flex: 6;
}
}
<div id="toolbox">buttons here</div>
<div id="fieldcode">
<div id="field">
<canvas></canvas>
</div>
<div id="code">
<div id="codemirror"></div>
</div>
</div>
<div id="console">console here</div>

Categories

Resources