CSS: Performance wise, better to use calc or position absolute - javascript

I have a container div with fixed height. Inside two divs, the top height: 50px and the other one must fill the empty space but allowing internal scroll.
Now I have two options:
#up{
height: 50px;
}
#down{
position: absolute;
top: 50px;
bottom: 0;
}
or:
#up{
height: 50px;
}
#down{
height: calc(100% - 50px);
}
If I have many of these cases inside my window, which one is the best to use performance wise?
This Fiddle
ps. I don't care about old browser support.

I would always work with calc option. Both could look the same but they are not.
When you use position:absolute You are taking the container #down out of the html flow.
This means that if anytime you are going to add more stuff to your project, You will have many problems positioning them.
As an example, if you want to add another container below #down (a footer maybe), in your first option it will be placed overlapping #down container right below your header. In the second option it will be placed where you want it.

One way to fill the space would be to use flexbox.
.container {
display: flex;
flex-direction: column;
height: 200px;
}
#up {
background: yellow;
flex: 0 0 50px;
}
#down {
background: orange;
flex: 1 1 auto;
}
<div class="container">
<div id="up">
up
</div>
<div id="down">
down
</div>
</div>

Related

How to make one div always be at the bottom of the view and make top div resize based on bottom div?

I'm pretty new to web development and I'm working on something which requires two divs to always take up 100% of the viewport.
I have div A which is an interactive image that should be as big as possible and should take up the top part of the screen.
Then div B which contains either 1 or 2 buttons depending on what action is done on the interactive div A. Div B is at the bottom of the view.
Is there a clean way to make the size of A depend on the size that div B takes up dynamically? Like just the "remainder" of the viewport should be div A. I put an image below of what I'm attempting to achieve. The second image shows what would happen if some action is done in div A - for simplicity, we could say if some method potato() is called, we want div B to now contain two buttons.
I have tried doing a solution with:
position: fixed;
bottom: 0;
and Div B looks 90% right that way, but it doesn't resize Div A and I also don't want Div B "covering" anything in this way. I just want it to be the same level as Div A and sharing the space to get 100% of the viewport.
Any help would be greatly appreciated! I'd prefer to use plain CSS if possible. I'm doing some away team work and can't add much in the way of libraries or new dependencies to the project.
check on this fiddle https://jsfiddle.net/kt931frp/1/ the trick is using flex as suggested by the below answer.
<div class="wrapper">
<div class="part1"></div>
<div class="part2">
<div contenteditable="true"class="contenteditable">continue typing...</div>
</div>
</div>
body {
margin: 0;
}
.wrapper {
height: 100vh;
display: flex;
flex-direction: column;
}
.part1 {
background:#ffff00;
flex: 1 0 auto;
}
.part2 {
padding: 2em;
color: white;
background:#ff0000;
}
.contenteditable{
width:100%;
min-height:50px;
}
Actually, this is pretty easy using Flexbox and the flex property.
You can change the padding value to see how the top block reacts.
body {
margin: 0;
}
main {
height: 100vh;
display: flex;
flex-direction: column;
}
.top-part {
flex: 1 0 auto; /* This tells `top-part` to take the remaining place. */
background: violet;
}
.bottom-part {
padding: 2em;
color: white;
background: lightblue;
}
<main>
<section class="top-part"></section>
<section class="bottom-part">
Some text here
</section>
</main>
Bringing my 2 cents, you can also take advantage of display: table|table-row|table-cell to create this layout (see the MDN documentation on display property to know more).
The trick when using these properties, unless display: flex, is to tell the "actions" cell to measure 0.1px, which will force the cell to be the minimum possible. However, it does not crushes its inner content, allowing to dynamically adjust depending the content inside.
As cells are by default sharing spaces, this does the job for this kind of layout because the "Div A" is using the rest of the available space.
Check this JSFiddle or use the snippet code below to play with it. I annoted the properties you can tweak.
body {
margin: 0px;
}
.app {
width: 100vw;
height: 100vh;
display: table;
}
.main,
.actions {
display: table-row;
}
.main > div,
.actions > div {
display: table-cell;
vertical-align: middle;
text-align: center;
border-width: 10px; /* tweak this */
border-style: solid; /* tweak this */
}
.main > div {
border-color: purple; /* tweak this */
background-color: violet; /* tweak this */
}
.actions > div {
padding: 20px; /* tweak this */
border-color: blue; /* tweak this */
background-color: lightblue; /* tweak this */
height: 0.1px;
}
.button {
width: 200px; /* tweak this */
padding: 10px; /* tweak this */
}
<div class="app">
<main class="main">
<div>
Div A
</div>
</main>
<footer class="actions">
<div>
<div>
Div B - some text and 2 buttons
</div>
<div>
<button class="button">
Button 1
</button>
</div>
<div>
<button class="button">
Button 2
</button>
</div>
</div>
</footer>
</div>
Hope it help you getting inspiration.

Fixed ratio column CSS puzzle

I am struggling to work the css out for this scenario. I have a fixed height header (no problem there). Underneath I have two side by side blocks.
The blocks should go from the header to the footer (with a small margin).
I would like the first block to have a minimum width of 25% of the browser width. The second block should have an aspect ratio of 4:3. It should be able to achieve this in most cases by expanding the first column past 25%.
In the cases when the first block can't shrink below 25% width, the right block should still be 4:3 but vertically centred in the view.
Is this possible with just CSS? I need to support modern browsers and IE 10.
Thanks
You can use code below:
header {
height: 50px;
}
.container {
display: block;
height: 100vh;
width: 100%;
display: table;
}
.left-block {
height: 100%;
min-width: 25%;
width: 25vw;
background: yellow;
}
.left-block,
.right-block {
display: table-cell;
vertical-align: middle;
}
.right-content {
background: blue;
width: 74vw;
height: calc(75vw * .75);
}
<header>
header
</header>
<div class="container">
<div class="left-block">left content</div>
<div class="right-block"><div class="right-content">right content</div></div>
</div>
Using the vwcss unit with a min-width on the yellow block should do what your wanting. Hard to say for sure with out a fiddle or codepen to look at your actual code.
min-width: 25vw;
width: 25%;
For the blue area at a 4:3 ratio you can use the vw css unit again for the width and use the calc function for the height.
width:75vw;
height: calc(75vw * .75);

Hide element "beneath" div of lower z-index

Two fiddles. The first, showing everything working as I want: http://jsfiddle.net/3SWwD
The second, showing the problem as it exists on the site I'm trying to deploy the effect on: http://jsfiddle.net/3SWwD/1/
Those fiddles describe everything this code does, but for thoroughness:
I have two container divs bumped up to one another, the first of which contains an imagel which I have simplified to <div id="image"> for this example.
<div id="container">
<div id="image"></div>
</div>
<div id="never_cover_me">
</div>
They are styled as follows, and theses styles will exhibit the issue, which I'll explain when I show the js.
#container{
height: 400px;
width: 400px;
background: blue;
position: relative;
z-index: 200;
}
#image{
height: 200px;
width: 200px;
background: red;
position: relative;
top: 200px;
left: 100px;
z-index: 50;
}
#never_cover_me {
position: relative;
height: 400px;
width: 400px;
background: yellow;
z-index: 100;
}
Lastly, some Jquery/JS moves the image down, thus into the space of #never_cover_me. If all was well in the world, #image would be covered by #never_cover_me while it was moved down, but since #container has a higher z-index than #never_cover_me, obviously that isn't the case and the image is instead drawn over #never_cover_me.
$(document).ready(function(){
setInterval(
function(){
$('#image').animate({top: '+=200px'}, "slow", function(){
$('#image').delay(1000).animate({top: '-=200px'}, "slow")
});
},3000
);
});
For various reasons, #container MUST have a higher z-index than #never_cover_me. Semantically, I would prefer if #image stays within #container.
Ideas?
The #container:
z-index: 200;
is above #never_cover_me:
z-index: 100;
Therefore, it is causing the issue you are experiencing. Here is more information on stacking order and how descendants are affected.
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Understanding_z_index/Stacking_and_float
You shouldn't really try to use other elements to hide your content. A better solution would be to set overflow:hidden; on #container because the effect you are going for is "hide this when the block is outside the current element."
It was as easy as adding overflow:hidden to #container.
Fiddle: http://jsfiddle.net/3SWwD/2/

Hide scroll bar of nested div, but still make it scrollable [duplicate]

This question already has answers here:
Hide scroll bar, but while still being able to scroll
(42 answers)
Closed 8 years ago.
This is a reference that I used, which explains how to make a div scrollable with its scroll bar hidden. The only difference is that I have nested divs. Check my fiddle
HTML:
<div id="main">
<div id="sub-main">
<div id="content">
<div id="item-container">
<div class="item">a</div>
<div class="item">b</div>
<div class="item">c</div>
</div>
</div>
</div>
</div>
CSS:
#main {
width: 500px;
height: 500px;
}
#sub-main {
width: 500px;
height: 500px;
overflow: hidden;
}
#content {
background-color: red;
width: 500px;
height: 500px;
overflow: auto;
}
#item-container {
width: 1500px;
height: 500px;
}
.item {
width: 500px;
height: 500px;
font-size: 25em;
text-align: center;
float: left;
}
Like above, I have a overflowed horizontal div and I want to hide its scroll bar. I have to make it still scrollable because $.scrollTo() wouldn't work otherwise.
UPDATE:
I have read all the answers, but I still have not resolved my problem and don't know what's causing it. This is the live that's having troubles.
Basically, I am trying to follow this almost exactly the same, but there must be some reason that my website isn't working as expected. There are two problems.
When I set overflow: hidden to a parent container of scrollable items, I cannot scroll (native javascript scroll functions do not work too).
I want to scroll just the overflowed container, not the entire window. This can be done by setting a target in $.localScroll({ target: '#projects-content' }) but nothing scrolls when I set the target. If I don't, scrolling works as long as overflow:hidden is not applied.
Again, any help would be greatly appreciated.
HTML:
<div id="projects"> <!-- start of entire projects page -->
<div id="project-sidebar">
<a href="#project-first">
<div class="sidebar-item sidebar-first">first</div>
</a>
<a href="#project-second">
<div class="sidebar-item sidebar-second">second</div>
</a>
<a href="#">
<div class="sidebar-item sidebar-third">third</div>
</a>
</div>
<div id="project-content"> <!-- this must be the scrollable itmes' container, not the entire window -->
<div id="project-first" class="project-item">
<!-- these items should be scrollable -->
<div class="project-subitem" id="first-sub1">
<a href='#first-sub2' class='next'>next</a>
</div>
<div class='project-subitem' id='first-sub2'>
<a href='#first-sub1' class='prev'>prev</a>
</div>
<!-- end of scrollable items -->
</div>
</div> <!-- end of scroll scroll container -->
</div> <!-- end of entire projects page -->
<script>
// FIXME: when I set target, nothing scrolls.
// But I don't want the entire window to scroll
$('#projects').localScroll({
//target: '#project-content',
hash: false
});
</script>
CSS
#project-content {
width: 80%;
height: 100%;
position: relative;
float: left;
}
#project-sidebar {
float: left;
width: 20%;
height: 100%;
}
.project-item {
width: 300%;
height: 100%;
}
.project-subitem {
height: 100%;
width: 33.33%;
position: relative;
float: left;
}
Update:
After I added overflow:scroll to #project-content, the scrolling works as expected. All I need now is making scroll bars disappear in #project-content. I tried adding overflow:hidden to its parent but had no success. I also tried adding it to html, body, but then the entire document refuses to accept any scrolling functions like scrollTop().
Any help will be greatly appreciated!
Theory :
The technique is to use a parent container that is shorter than the child element with scrollbar. This image shows what I mean :
Practice :
In your case, I suggest using absolute positionning and negative bottom value on #project-content so it overflows it's parent container (#projects) at the bottom.
The point is now what negative value? It should be the same value as the with of a scroll but scrollbars are never the same width according to browsers. So I suggest giving a bigger value : -30pxto be sure it is hidden. You will just need to be carefull that you don't have content to close to the bottom that can be hidden on browesers with thin scrollbars.
This is the CSS you should add to your website :
#projects{
position: relative;
}
#project-content{
position: absolute;
top: 0;
left: 20%;
bottom: -30px;
/* remove:
height: 100%;
position: relative;
float: left;
padding-bottom: -15px
/*
}
scollbars take up around 20px so just make you scrollable div 20px taller and 20px wider and your scrollbars will be hidden:
#content {
background-color: red;
width: 520px;
height: 520px;
overflow: auto;
}
Example
It's kind of cheating but could you hide it behind the #content like this DEMO
#content {
background-color: red;
width: 500px;
height: 480px;
overflow: hidden;
}
#item-container {
width: 1500px;
height: 500px;
overflow: scroll;
}
If you know all containers that can be scrollable, you can hide scrollbar with CSS and a little bit of JS. For webkit-based browsers (safari, google chrome, opera) it will be CSS-only solution to set scrollbar width to 0. For IE, Firefox and other non-webkit browsers you should calculate scrollbar width that will be used as negative margin-right for you scrollable content.
To do so you should wrap your content into div with overflow-y:scroll to always show vertical scrollbar and hide this scrollbar with margin-right:-17px and parent overflow:hidden. Example is here. No need to set fixed width, nor height.
This is the way that used in jQuery Scrollbar. Hiding horizontal scrollbar is more complicated and requires to handle content changes to recalculate container height.
I basicly add padding:0 1em 1em 0; to the element where it is supposed to be hidden , this hides both scrollbars if parent has overflow: hidden. tune padding-bottom or only padding-right, if it is to hide only one of them.
1em is average width of scroll bars in most browsers :
http://jsfiddle.net/5GCsJ/912/
The solution to make the content itself with horizontal scroll.
Just increase the height of #main, and #content.
#main {
width: 500px;
height: 520px;
}
#sub-main {
overflow: hidden;
}
#content {
background-color: red;
width: 500px;
height: 520px;
overflow: auto;
}
#item-container {
width: 1500px;
height: 500px;
overflow: hidden;
}
.item {
width: 500px;
height: 500px;
font-size: 25em;
text-align: center;
float: left;
}
Use a script to create custom scrollbars.
http://manos.malihu.gr/jquery-custom-content-scroller/
Then use CSS(or modify script or change script config) to hide the custom scrollbars.
I did this crudely using jQuery and your example
Check this fiddle:
I simply detected the direction of the scroll-wheel and pushed the horiz-scroll bar with jQuery
$(document).ready(function(){
$('#content').bind('mousewheel', function(e){
var curScroll = $("#content").scrollLeft();
if(e.originalEvent.wheelDelta > 0) {
$("#content").scrollLeft(curScroll-500);
} else {
$("#content").scrollLeft(curScroll+500);
}
});
});
It is "crude" because I hard-coded some values like the 500px amount to scroll, you could write some more javascript to detect dynamically how much to scroll. Plus I don't know if the wheelDelta value will be +120 for up and -120 for down, for you and other users.
Also note that the scrolLeft() can be animated.. for smoother transitions.

Centering Dynamic width Divs

I have a page that has 2 columns. The first column is a dynamic width. It contains a bunch of tabular data in tables. The 2nd column is a fixed width full of navigation stuff.
The 2 columns are divs with float left. I need to accomplish 2 things.
I need to center the 2 divs on the page. For example, if the first div is 600px wide as dictated by the data inside of it and the second div is a fixed 200px, the centering point is 400px.
I don't want the 2nd div to wrap down if the browser window is resized.
I'm thinking that I may have to nest the 2 divs inside of another div, set the parent div width using javascript, then center it.
I created this fiddle to help illustrate. http://jsfiddle.net/darthg8r/uhKdt/
Surround them with a div and set its style to:
width: ( whatever you need )
margin: 0 auto; // this centers the div
You can set the width dynamically with JavaScript if needed. As long as it's smaller than 100% of the surrounding container, it will stay centered.
You could achieve this with the following code:
HTML:
<div id="wrapper">
<div id="container">
<div id="variable">test</div>
<div id="fixed">test</div>
</div>
</div>
CSS:
#wrapper { overflow: hidden; }
#container {
float: left;
position: relative;
left: 50%; }
#container > div {
float: left;
position: relative;
right: 50%;
height: 300px; }
#variable {
background: red;
width: 300px; }
#fixed {
background: blue;
width: 200px; }
Preview: https://jsfiddle.net/Wexcode/mreLt/
You could also achieve this effect by wrapping the two elements in a container, setting them both to display: inline-block, and finally setting their container to have text-align: center.
The answer is a little more complicated than this, so let me know if you want to choose this route instead.
To make it so the elements don't fall to the next line, use inline-block.
<div id="container">
<div id="variable">
<p>test</p>
</div><div id="fixed">
<p>test</p>
</div>
</div>
CSS:
body { margin: 0; }
#container {
color: #fff;
text-align: center;
white-space: nowrap; }
#container > div {
height: 300px;
display: inline-block; }
#variable {
background: red;
width: 100px; }
#fixed {
background: blue;
width: 200px; }
Preview: https://jsfiddle.net/Wexcode/mreLt/2/

Categories