Increase padding on X elements when Y element's width decreases - javascript

The body element by default is of course taking up 100% width so when the browser window is resized this width in pixels will obviously decrease. For every pixel the body width is decreased I want to increase the padding of a group of elements ( header, main, and footer ) by 1 pixel. Not sure where to start. Here is a basic set up:
function start() {
//code here..
}
start();
#import url( 'https://necolas.github.io/normalize.css/latest/normalize.css' );
* {
box-sizing: border-box;
}
html, body {
height: 100%;
}
body, header, main, footer {
padding: 1%;
}
header, main, footer {
height: 33.333%;
}
div {
height: 100%;
background-color: #444;
color: #ddd;
}
p {
margin: 0;
padding: 0;
position: relative;
top: 50%;
transform: translateY( -50% );
text-align: center;
}
<header>
<div>
<p>When this snippet is made <b>Full page</b>.</p>
</div>
</header>
<main>
<div>
<p>And the browser window width is <i>decreased</i>.</p>
</div>
</main>
<footer>
<div>
<p>The padding on these rectangles should <i>increase</i>.</p>
</div>
</footer>
When the browser window is resized and body width decreased I want the padding value on header, width, and height to increase proportionately.
I originally tried accomplishing this without JavaScript utilizing CSS viewport units. That did not work out very well.
PS: I'm trying not to use Jquery.
EDIT: I just realized this but it might be worth pointing out that the default padding behavior is to decrease in value as the containing elements width decreases. As both top & bottom and left & right padding is calculated by the containers width as can be seen when my snippet is resized.

padding: 0 calc( 500px - 50vw );
This works, but only for a limited range of viewport sizes (500px - 1000px).
The issue with doing the calculation in just CSS is that there will have to be a defined upper and lower bound, because viewports could in theory be thousands of pixels wide and it will have exhausted the amount of padding available to it at some point.
My code works by setting the upper limit with the value of 500px, so 1000px total when applied to left and right, and then the lower limit is the half of that by the value of 50vw, or in other words 50%. If you play with these values you can hopefully align the upper and lower bounds to suit your needs.
http://codepen.io/zepha/pen/QpMRYQ

Related

Sticky element doesn't work well with scale

I have a div element which is set to 'sticky' to top of its parent div. The parent div is inside a div which is scaled. While everything works as expected if scale is set to 1, the sticky element doesn't stick if the scale is set to non 1 values, such as 1.5 or 0.5.
Please see the code here:
.scale {
height: unset;
transform: scale(1.5);
transform-origin: left top;
width: calc(66.6667%);
}
.container {
height: 1200px;
border: 1px solid;
}
.sticky {
position: sticky;
top: 0;
z-index: 1;
background: red;
}
<html>
<body>
<div class='scale'>
<div class='container'>
<div class='sticky'>
I should stick to top
</div>
</div>
<div>Other parts needed to scale</div>
</div>
</body>
</html>
If we set scale to 1.5 (transform: scale(1.5)), the sticky element is moving to the bottom as I scroll the page. If I set scale to 0.5, it will just scroll off the screen. If it's set to 1, everything works fine.
I am wondering how to keep both the 'sticky' and 'scale' working in this scenario. Thanks for any help!
The problem is that you're scaling the parent div, if you use 1 as a scale then the sticky div will move by 1:1 ratio
1.5 as scale will be 1.5:1 ratio so when you scroll by 100px, the sticky div will move 150px, making it go down
0.5 as scale will be 0.5:1 so it so it will move by 50px if you scroll down 100px, making it look like it's moving up

Setting `element.style.height` not working as expected if `element.style.box-sizing` is `border-box`

I am having an understanding problem with the following code:
let myDiv1 = document.getElementById("myDiv1");
alert("Click me to make 'Hello' vanish");
myDiv1.style.height = "0px";
let myDiv2 = document.getElementById("myDiv2");
alert("Click me to make 'World' vanish");
myDiv2.style.height = "0";
.myClass1 {
box-sizing: border-box;
overflow: hidden;
padding-top: 2em;
padding-bottom: 2em;
background-color: yellow;
}
.myClass2 {
box-sizing: content-box;
overflow: hidden;
padding-top: 2em;
padding-bottom: 2em;
background-color: orange;
}
<body>
<div id="myDiv1" class="myClass1">
Hello
</div>
<div id="myDiv2" class="myClass2">
World
</div>
</body>
I understand the behavior of the second (orange) div: It has box-sizing: content-box;, so its height does not include the padding or the borders. Hence, when its height is set to 0, it shrinks basically by the height of the text "World", but the padding is left as-is. Since the padding exceeds the original text height, the text is still visible in the padding. Only that part of padding which is now outside the div (due to the reduced height) becomes invisible (due to overflow: hidden;).
I do not understand the behavior of the first (yellow) div, though. It has box-sizing: border-box;, so its height does include the padding and the borders. Hence, when its height is set to 0, it should shrink to "real" zero height, meaning that the text, the padding and the borders then should be outside the div and thus should be invisible (due to overflow: hidden;).
Can anybody explain why this is not the case and why the first div behaves just like the second div?
P.S. Tested in Firefox and Chrome, both up-to-date (production channel) at the time of writing this.
border-box tells the browser to account for any border and padding in the values you specify for an element's width and height. If you set an element's width to 100 pixels, that 100 pixels will include any border or padding you added, and the content box will shrink to absorb that extra width. This typically makes it much easier to size elements. ref
Here is an example to better ilustrate your issue:
.box {
display: inline-block;
padding-top: 2em;
padding-bottom: 2em;
border: 2px solid blue;
background: linear-gradient(red, red) content-box, orange;
height: 100px;
animation:move 5s linear infinite alternate;
}
#keyframes move{
to {
height:0;
}
}
<div class="box">
World
</div>
<div class="box" style=" box-sizing: border-box;">
World
</div>
The first example is the trivial one where we decrease the height (red area) until 0 and the animation never stop.
In the second case the height include the padding and border so before reaching 0 the content area is already 0 that's why the animation seems to stop because we cannot decrease more than 0 and the border/padding already consumed all the space.
It's logical that when height is equal to 0 both are the same since in the first one we tell the browser that the content area should be 0 (we don't care about padding/border) and in the second case we told the browser to account for the padding/border into the height we specified so we have less room for the content area and since we cannot have less than 0 then its 0.
In other words, you aren't setting the total height that will be split between the content area, padding and border but you are setting a height and the browser is shrinking it as much as possible to include the border and padding.
Related for more examples and details: box-sizing: border-box with no declared height/width

Get a Circles Width Defined by a Percent in Pixels and apply them to the Height Value

After 4 hours of trial and errors, I cannot find a way to get the width of the circle that is defined by a percent and convert it to pixels and make the circles height the same size as the width in pixels. Below is what I have right now. (I have tried many variations of this but cannot figure it out) Right now it only works on my screen. I try it on other devices and the height is just not right. This button is created onload.
Example: Circle Width = 12% , the Pixel Value of 12% on a screen is "70px". So somehow make Circle Height = 70px.
<!DOCTYPE html>
<head>
<title>Circle Test</title>
<meta charset='UTF-8'>
<script type="text/javascript" src="/js/fs"></script>
</head>
<body>
</body>
</html>
// Creates a button
var mainButton = document.createElement("button");
mainButton.style.width = "10%";
// Get the Screens Avaliable Width and Get 10% of it and convert it to pixels
var wad = screen.availWidth * .1 + "px";
// Thinking this would return the pixel amount the circle button is, but it only works on the regular screen and not when resized. It also does not work for mobile.
console.log(wad);
mainButton.style.height = wad;
You set the width of your button to 10% of its containing block's width, and the height to 10% of the width of one of
The available area of the rendering surface of the output device, in CSS pixels.
The area of the output device, in CSS pixels.
The area of the viewport, in CSS pixels.
It's very likely that these are measurements of two different things, or that resizing the window will affect one but not the other. Fortunately, CSS has a unit for "percentage of the window's width": vw. Set your button's height and width in vw units, and you don't need any JavaScript:
button {
width: 10vw;
height: 10vw;
border-radius: 50%;
}
<button>Go</button>
If you really meant that the button is 10% as wide as its container, even if its container isn't as wide as the whole window, you can use the padding-bottom technique detailed in this answer. Unlike height, percentages in padding refer to the width of the containing block:
.wrapper {
width: 40%; /* here I use 40% instead of 10% for aesthetics */
padding-bottom: 40%; /* should match width */
position: relative;
}
.wrapper > button {
display: block;
position: absolute;
width: 100%;
top: 0;
bottom: 0;
border-radius: 50%;
}
/* the rest is just to make figuring out
the exact width of the button difficult */
body {
display: flex;
align-items: stretch;
height: 90vh;
}
body > div {
flex: 1 1 0;
background: rebeccapurple;
margin: 0 4px;
}
<div>
<div class="wrapper"><button>Go</button></div>
</div>
<div></div>
<div></div>
And finally, just for completeness, if you really must get the computed width from JavaScript, you can use window.getComputedStyle:
let button = document.querySelector('button');
let width = window
.getComputedStyle(button)
.getPropertyValue('width');
console.log(button.style.height = /* DO NOT DO THIS */ width);
button {
width: 40%;
border-radius: 50%;
}
/* the rest is just to make figuring out
the exact width of the button difficult */
body {
display: flex;
align-items: stretch;
height: 90vh;
}
body > div {
flex: 1 1 0;
background: rebeccapurple;
margin: 0 4px;
}
<div>
<button>Go</button>
</div>
<div></div>
<div></div>
If you try putting that into a resize handler, though, performance will suffer.

Position fixed elements to stick the edges of their sibling

How can I make two fixed elements stay with their sibling element.
<div class="left-img"> IMAGE HERE </div> <!-- fixed positioned -->
<div class="container"> Lorem ipsum... </div>
<div class="right-img"> IMAGE HERE </div> <!-- fixed positioned -->
Here is a fiddle. So far I set:
top: 50%;
To center it vertically. But when the window re sizes horizontally the fixed elements are need to stay with their sibling, the container. How in jQuery or CSS can I do this?
I thought about doing something like
$(window).resize(function() {
$('img').css("right", /*size here*/);
$('.right-side-img');
})
But I'm not sure how I would set the window size. I'm using bootstrap so all my content is in the container and I would like to set an image to stay in the middle on the outside of each side.
You could achieve that by setting an explicit width of the left and right absolutely positioned elements and using a proper value for left/right properties.
Example Here.
.left-img,
.right-img{
position: fixed;
background: blue;
top: 50%; /* <------ 15% -----> */
width: 12%; /* = ((100% - 70%) / 2) - 3%
| | | |
width of the body --- | | --- needed gap for left/right (*)
width of the container ----- ----- get remaining width for each side */
}
.left-img { left: 3%; } /* (*) The gap between edges of the page and elements */
.right-img{ right: 3%; }
For unequal widths you could use CSS3 calc() function in order to calculate the needed value for left and right properties depending on the width of each fixed positioned element.
Example Here
.left-img {
width: 150px;
left: calc(15% - 150px);
}
.right-img{
width: 100px;
right: calc(15% - 100px);
}
It's worth noting that calc() is supported in IE9+.
Here is the old answer which seems to be under a misunderstanding

Changing footer position to be at the bottom of page until it hits content

(I am looking for an HTML/CSS fix but if there really is none then JS (prefereably JQuery) works for me)
I have two main divs inside my page, I have the #maincontent and the #footer.
Basically, I want the footer to always sit at the bottom on the page:
#footer{
position:fixed;
bottom:0;
}
BUT I do not want it to overflow on the #maincontent when the page is too small.
For the sake of the question the page can be thought of as simple as:
<body>
<div id="maincontent">Dynamic Content</div>
<div id="footer">StaticContent</div>
</body>
My problem is that I can do one or the other, either I fix it to the bottom of the page but when I make the viewport < (footer + maincontent) the footer sits on top of the content. I want the footer to always be at the bottom of the page but disappear off page before it overtakes the main content.
Add a class to the footer with jQuery that changes it to position: absolute when the viewport is too small.
$(document).ready(function() {
var height = $(window).height();
function windowHeight() {
height = $(window).height();
}
windowHeight();
$(window).resize(function() {
windowHeight();
});
if (height < 600) { //arbitrary height value you can set yourself
$('#footer').addClass('not-fixed');
} else {
$('#footer').removeClass('not-fixed');
}
});
If you know your footer's height whatever happens to the window height, or its content :
Just add a "padding-bottom" to your body or main content that matches the footer's height.
If you don't know your footer's height. This is trickier, as you will probably need some javascript to calculate the height of the footer, the height of the main content, compare the sum of both with the window height, and if it doesn't fit, add some adequate bottom padding to the body / main content.
EDIT :
Ok I understand, I think this jsfiddle should do the trick : http://jsfiddle.net/ah4XA/2/
The javascript would be :
$(document).ready(function () {
function updateFooter () {
var footerH = $("#main-footer").height();
var contentH = $("#main-content").height();
var windowH = $(window).height();
if ( contentH + footerH > windowH) {
$("#main-footer").removeClass("fixed");
} else {
$("#main-footer").addClass("fixed");
}
}
$(window).resize(function () {
updateFooter();
});
updateFooter();
});
If I understand what you're looking for, you want the footer to stay on the bottom of the window regardless of the page content, but also not overlap the page as the window is resized vertically.
One possible solution is to switch between position:absolute; and position: fixed; with a media query. So past a certain height it's fixed, but below that the footer position:absolute;.
EXAMPLE FIDDLE
CSS:
#media all and (max-height:300px) {
#footer {
background: red; <- added for testing
position: absolute;
}
}
The only drawback to this approach is that you need to know the height to set the switchover to. This may be tricky, but position:fixed;.
The simplest solution would be to position footer at the bottom permanently and increase the z-index of your maincontent so that it comes over the footer if window size is decreased.
NOTE: This is not the only way to do this.
JSFIDDLE DEMO
Sample CSS
#maincontent{
height : 400px;
background-color : green;
/*
position : relative is added to enable z-index.
*/
position:relative;
/*
z-index will bring it above footer,
if window size is reduced.
*/
z-index: 1;
width : 100%;
}
#footer{
height : 100px;
width : 100%;
background-color : black;
/* Below two properties will
postion footer at the bottom of the page.
*/
position : fixed;
bottom : 0;
color : white;
}
You should play with CSS position property to get this done.
EDIT:
Here is another CSS solution :
The maincontent and footer are wrapped in a bodyContainer div its position is set to relative and then footer is positioned w.r.t it.
JSFIDDLE DEMO 1 Footer is below body and not shown.
JSFIDDLE DEMO 2 Footer is shown since body height is less.
HTML
<div id="bodyContainer">
<div id="maincontent">Dynamic Content
</div>
<div id="footer">StaticContent</div>
</div>
CSS
#bodyContainer {
min-height: 100%;
position: relative;
}
#maincontent{
height : 800px;
background-color : green;
padding-bottom: 60px;
width : 100%;
}
#footer{
background-color: black;
bottom: 0;
color: #FFFFFF;
height: 48px;
position: absolute;
width: 100%;
}

Categories