I've seen others use overflow-y:scroll to make a div move with scroll almost like a scrollbar, however my fixed css configuration doesn't let that work.
I just have a div.
<div class="scrollBar"></div>
.scrollBar {
width: 2px;
height: 45px;
background: white;
margin-left: 46%;
overflow-y: scroll;
position: fixed;
}
I've now tried to animate the div moving up or down with the scroll event using jquery/Tweenlite, however this isn't eloquent/effective.
var multi = event.deltaY >= 0 ? 1 : -1;
var change = (multi * 10).toString + "px";
TweenLite.to($('.scrollBar'), 1, {
"margin-top": change
});
How can I do this either via css or jquery?
css/html for the frame that houses the scroll bar:
<div class="frame">
<div id="rightCol">
<p>[</p>
<div class="scrollBar">
</div>
<p>]</p>
.frame {
display: grid;
width: 100vw;
height: 100vh;
grid-template-areas:
"leftCol topBar rightCol"
"leftCol center rightCol"
"leftCol bottomCol rightCol";
grid-template-rows: 10% 80% 10%;
grid-template-columns: 10% 80% 10%;
padding: 3.2rem;
z-index: 10000;
}
Related
I have a react app where I'm creating about a million grid boxes, all the boxes ought to fit into the immediate screen (I want each box to be tiny asf). I'm using js to calculate each box's height and width in relation to the number of boxes.
var numOfBoxes = 1000 // this number can change anytime
var [height, width] = `${100/numberOfBoxes}%`
I created the grid using a CSS I found on StackOverflow
#root {
width: 100vw;
height: 100vh
}
// I tried to use vh and vw to make the #root element fit the initial screen
.square-container {
display: flex;
height: 100%;
width: 100%;
flex-wrap: wrap;
}
.square {
position: relative;
flex-basis: calc(25% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0; left: 0;
height: 100%;
width: 100%;
}
But the squares remain the same size when I try to increase or decrease numOfBoxes. I tried changing the height and width from the DevTools but to no avail.
It looks like this if I render 100 boxes or 1000
Can someone point me in the right direction?
You can add a CSS variable to the root element, use it as part of the grid class, and then update it with setProperty.
// Using a setTimeout for this demo, but you would
// be adding this to your render method I expect
function changeWidth(width, count = 1) {
document.documentElement.style.setProperty('--square-width', `${width}px`);
if (count < 5) setTimeout(changeWidth, 2000, width +=5, ++count)
}
changeWidth(5);
:root {
--square-width: 10px
}
.container {
display: grid;
grid-template-columns: repeat(3, var(--square-width));
grid-gap: 5px;
}
.container div {
background-color: red;
aspect-ratio: 1;
}
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
I'm facing problem with breaking the line on website. What do I mean?
HTML code
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
With such HTML code I'd like to have:
fixed height on main element (for example 80vh)
fixed height for all the elements first and third 40vh + second 80vh
fixed width for first and third element 50vw
fluid width for second element - but this is main problem - second element has to be in the same place and grow horizontally (to create scroll on the bottom of the site)
Please find my codepen
I've added button that'll add pixels to second element - but it destroys my website.
I'm not sure if flexbox is better than floats.
I'll appreciate any tip.
Here is the snippet:
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50% + ${counter}px)`;
console.log(counter);
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
max-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
float: left;
}
.third {
background-color: red;
}
.second {
height: 80vh;
width: 50%;
float: right;
background-color: blue;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
<main class="clearfix">
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
I would suggest you to go with position properties. Since you have a little difference between the order of your DOM element and their visual representation, like 1,2,3 in the DOM, but visually it's more like 1,3,2.
However, in such situation float is your enemy. I'm not 100% sure about flex, AFAIK flex would keep all the elements inside the parent element and prevent the scrolling.
If you go with absolute positioning, (since you already have the heights and widths defined)
Apply:
position: relative to the main element, it will be the base point of the child elements if they are set to absolute.
overflow-x: scroll to the main element. it will allow you to scroll horizontally when you increase the width of your second element.
position: absolute on .first, .second, .third, as you have the height and width defined, now set their position accordingly, check the snippet, you'll get it.
Finally you're good to add more value to your width of the target element.
Tip: always keep a consistency in your css units, for example, if used vh / vw use this for similar elements at least, or if px / em / rem is used, try to use the same accordingly.
Check the snippet in full page mode
let counter = 0;
document.querySelector("button").addEventListener("click", function() {
document.querySelector(".second").style.width = `calc(50vw + ${counter}vw)`;
document.querySelector("#added").textContent = counter;
counter++;
});
* {
padding: 0;
margin: 0;
}
main {
overflow-x: scroll;
position: relative;
min-height: 80vh;
}
.first,
.third {
height: 40vh;
width: 50vw;
background-color: black;
position: absolute;
left: 0;
top: 0;
}
.third {
background-color: red;
top: 40vh;
}
.second {
height: 80vh;
width: 50vw;
background-color: blue;
position: absolute;
left: 50vw;
top: 0;
}
button {
margin: 30px 5px;
border: 1px solid #cecece;
padding: 5px 10px;
}
<main>
<div class="first"></div>
<div class="second"></div>
<div class="third"></div>
</main>
<button>Add</button>
<p><span id="added">0</span>vw Added to blue div's width</p>
I have a div element (shown with red border in the image below), which I want to be able to fit in its parent div when the window is resized and not fall into the next line (the parent is the one with the green border).
I want the red div to have a starting width: 949px (in my current screen) in order to fit the entire space available as shown in the image, but be resizable, so that it doesn't fall into the next line if width: 949px is to much to fit.
In essence, I want it at all costs to cover the area it covers in the image even if in a narrower screen that means it will be like 10px wide.
How can I achieve this? Any solution using CSS, JavaScript or jQuery will be gladly accepted.
The image:
CSS:
#parent {
text-align: center;
width: 90%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: inline-block;
}
#child1-row2 {
text-align: left;
vertical-align: middle;
width: 288px;
display: inline-block;
}
#child2-row2 {
text-align: left;
vertical-align: middle;
width: 288px;
position: relative;
margin: 0 25px 0 25px;
display: inline-block;
}
#child3-row2 {/* The one with the red border */
vertical-align: middle;
height: 452px;
width: 949px;
overflow: hidden;
position: relative;
display: inline-block;
}
You can use flexbox to do this by using the flex-grow property.
HTML :
<div id="main">
<div id="box1">1</div>
<div id="box2">2</div>
<div id="box3">3</div>
</div>
CSS :
#main {
display: flex;
flex-flow: row;
width:100%;
min-height:50px;
}
#box1{
background-color:red;
width:100px;
}
#box2{
background-color:blue;
width:100px;
}
#box3{
background-color:green;
flex-grow: 1;
}
Here is a working JSFiddle
You can use css calc function for this. Support for calc seems to be quite good now.
As you have mentioned, the left side divs are of fixed width, say 120px each. Also suppose the margin between them is 30px. So, the total width left for your red div is 100% - (2*120 + 2*30)px i.e. (100% - 300px ).
#red-div
{
width: calc(100% - 300px);
}
Add % width or you can do following :
$(window).resize(function() {
var window_width = $(window).width();
var w1_width = $('.div1').width(); // The first element width
var w2_width = $('.div2').width(); // The second element width
var main_div_width = window_width - (w1_width+w2_width+gutter[i.e margin between all 3 elements]);
$('.main_div_width').css('width', main_div_width);
});
I'm trying to make a a page container with a navigation bar on the left (inside of the container). When the outer page is wider than the container, I would like just the navigation bar to extend left up to a certain size while the rest of the container's contents to remain the same and stay in the middle of the outer page.
To illustrate my idea, here are the before and after images, with black representing the outer page, blue the page container, pink the leftnav, and green the rest of the container.
Here is also the general structure of the code I am writing. The jsfiddle link includes some css for detail.
<div id="page">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
https://jsfiddle.net/6L1zrj6e/1/
Currently, my container has a fixed width and automatic margins so as to center it. Is what I am trying to achieve even possible with the current layout? Would I need to move the leftnav div outside of the container?
Here's a pure css solution: fiddle
This is a trick I learned here: here
where you have to put the float first, then make the div respect it by creating a new block formatting context, then the div will expand to the remaining space. Throw in a couple min/max widths to conform it and a wrapper with min/max widths as well and it falls into place. The html background makes the body background not extend past the body as it normally would. Another little trick.
<div class="wrap">
<main></main>
<nav></nav>
</div>
html {
background: white;
}
body {
background: purple;
padding: 0;
margin: 0;
}
.wrap {
margin: 0 auto;
max-width: 1080px;
min-width: 920px;
}
nav {
overflow: auto; /* force a new context to respect float */
background: red;
height: 300px;
min-width: 200px;
max-width: 360px;
}
main {
float: right;
background: green;
height: 300px;
width: 720px;
}
You can try the following: Full screen example
jsFiddle
HTML:
(Took leftCol out of container)
<div id="page">
<div id="leftCol">
LEFT
</div>
<div id="container">
<div id="rightCol">
RIGHT
</div>
</div>
</div>
JS: (Update the width on page resize and on load)
$(window).on('resize', function(){
var containerWidth = 980;
var pageWidth = $(window).width();
var tempW = Math.max(0, pageWidth-containerWidth) / 2;
tempW += 200;
var w = Math.min(tempW, 360); // 360 = max width
var l = Math.max(0, tempW - w);
$('#leftCol').css({'width': w+'px', 'left': l+'px'});
}).resize();
CSS: (Removed floats, using absolute position for leftCol)
#page{
background-color: purple;
position:relative;
}
#container {
background-color: blue;
width: 980px;
height: 300px;
margin: 0 auto;
}
#leftCol {
position:absolute;
top: 0;
left: 0;
background-color: red;
height: 300px;
width: 200px;
}
#rightCol {
padding-left:200px;
background-color: green;
height: 300px;
width: auto;
}
This is what I think you're after - forgive me if I'm wrong!
EDIT: Added outer container wrapper for right margin:
Updated HTML:
<div id="page">
<div id="outercontainer">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
</div>
</div>
And the CSS:
#page{
background-color: purple;
height: 300px;
}
#outercontainer {
margin: 0 5% 0 0;
}
#container {
background-color: blue;
height: 300px;
margin: 0 auto;
min-width: 300px;
max-width: 600px;
position: relative;
}
#leftCol {
background-color: red;
height: 300px;
margin-right: 200px;
}
#rightCol {
position: absolute;
background-color: green;
width: 200px;
top: 0;
right: 0;
bottom: 0;
}
This gives the #container a min and max width, and the margins will show beyond the max. These are set quite small to show up well in JSFiddle.
leftCol will expand to fit the available space, and it's right-margin prevents it overflowing the rightCol.
rightCol is absolutely positioned (within #container) in the leftCol's margin.
JSFiddle here: https://jsfiddle.net/xuew6og5/1/
The #outerwrapper allows a visible right margin, until the page gets to minimum width at least. If you want the margins to be balanced, change its margin to 0 5%
Update: New JS Fiddle with right margin: https://jsfiddle.net/xuew6og5/2/
Update 3: Sorry, I missed your requirement for a max-width of 360px on the leftCol. Updated the CSS above, and a fiddle here: https://jsfiddle.net/xuew6og5/4/
In order to achieve the wanted effect you need to move the leftCol outside of your container and give your rightCol a margin-left with the size of your leftCol.
Also add a min-width and max-width to your lefCol and a width using calc to adjust it's width to your goals.
Note: lefCol width is calculated like this:
100% / 2 - (Container width / 2 - leftCol min-width)
So your altered html looks like this:
<div id="page">
<div id="leftCol">
LEFT
</div>
<div id="container">
<div id="rightCol">
RIGHT
</div>
</div>
</div>
Your new CSS looks like this:
#page{
background-color: purple;
}
#container {
background-color: blue;
width: 300px;
height: 300px;
margin: 0 auto;
}
#leftCol {
float: left;
background-color: red;
height: 300px;
min-width:100px;
width:calc(100%/2 - 50px);
max-width:200px;
}
#rightCol {
margin-left:100px;
background-color: green;
height: 300px;
width: 200px;
}
Take a look at the updated example:
https://jsfiddle.net/xxyv7nwf/2/
CSS solution using CSS3 calc.
Edited. According to OP updates.
#media screen and (min-width: 1600px) {
#container{
margin:0 auto;
}
}
body {
overflow-x:hidden;
}
#page{
background-color: purple;
height:300px;
}
#container{
background-color: blue;
min-width:980px;
max-width: 1140px;
}
#leftCol {
float: left;
background-color: red;
height: 300px;
width: calc(100% - 780px);
}
#rightCol {
float: left;
background-color: green;
height: 300px;
width: 780px;
}
HTML
<div id="page">
<div id="container">
<div id="leftCol">
LEFT
</div>
<div id="rightCol">
RIGHT
</div>
</div>
</div>
I'm trying to setup the css for a native javascript animation. There are going to be several images that enter a "window" which is 600px. As one image slides in or out, the only visible part will be the part of the images that is within the window. I've had several attempts at setting this up with css before I start javascript animating, which include things like overflow:hidden on the rotator div and setting it's width, however that doesn't seem to work.
#rotator {
width: 600px;
height: 320px;
background: #131313;
/*text-align: left;*/
/*display: inline-block;*/
overflow: hidden;
/*position: relative;*/
/*float: left;*/
}
.box_wrapper {
width: 450px;
/*position: absolute;*/
display: inline-block;
/*overflow: hidden;*/
}
<div id="rotator">
<div class="box_wrapper">
<h4>Header1</h4>
<img src="../img/kat_3.jpg" /><br/>
</div>
<div class="box_wrapper box_2">
<h4>Header2</h4>
<img src="../img/kat_2.jpg" /><br/>
</div>
</div>
The images either fully show up or not at all when messing with the css properties.
you need set the width or height of the images, so they can be scaled into the the divs.
<style>
#rotator {
width: 600px;
height: 320px;
background: #131313;
overflow: hidden;
}
.box_wrapper {
width: 450px;
height: 100%;
display: inline-block;
}
</style>
$('.box_wrapper').each(function() {
var $el = $(this), $img = $el.find('img'), fixedRatio = 600 / 320,
ratio = $img.width() / $img.height(),
offset = $img.offset().top - $el.offset().top;
if (ratio > fixedRatio) {
$img.width($el.width()).height('auto');
} else {
$img.height($el.height() - offset).width('auto');
}
});