How do I scale this layout? - javascript

Been working on this layout for some time now and each way I take I run into some sort of obstacle (v1 of this here: https://stackoverflow.com/questions/14572569/how-can-i-contain-pos-abs-div-within-specific-area)
What I'm trying to do now is to have the size of .spread adapt to the browser windows width and height, so it'll never exceed what the user currently can see in their browser (.spread currently have fixed width/height, for demo purposes). The ideal would to be able to resize on the fly and it adapts instantly (i.e. no media queries).
It works as it should in the v1 version I link to above, but then I had problems with the fade effect due to that .spread lacked an actual width/height.
Here's the new demo:
http://jsbin.com/uciguf/1
UPDATE: The markup can be changed as long as it works as described.
<div class="scrollblock" id="scroll_spread-1">
<div class="action"><!-- --></div>
<!-- -->
</div>
<div class="scrollblock" id="scroll_spread-2">
<div class="action"><!-- --></div>
<!-- -->
</div>
<div class="contentblock" id="spread-1">
<div class="inner windowwidth windowheight">
<div class="content">
<span></span>
<div class="spread">
<div class="fade"><!-- --></div>
<div class="left centerimage">
<img src="http://s7.postimage.org/8qnf5rmyz/image.jpg">
</div>
<div class="right centerimage">
<img src="http://s7.postimage.org/kjl89zjez/image.jpg">
</div>
</div>
</div>
</div>
</div>
<div class="contentblock" id="spread-2">
<div class="inner windowwidth windowheight">
<div class="content">
<span></span>
<div class="spread">
<div class="fade"><!-- --></div>
<div class="left centerimage">
<img src="http://s7.postimage.org/5l2tfk4cr/image.jpg">
</div>
<div class="right centerimage">
<img src="http://s7.postimage.org/fjns21dsb/image.jpg">
</div>
</div>
</div>
</div>
</div>
html {
height: 100%;
}
body {
background: #eee;
line-height: 1.2em;
font-size: 29px;
text-align: center;
height: 100%;
color: #fff;
}
.scrollblock {
position: relative;
margin: 0;
width: 100%;
min-height: 100%;
overflow: hidden;
}
.contentblock {
margin: 0;
width: 0;
min-height: 100%;
overflow: hidden;
position: fixed;
top: 0;
right: 0;
}
.contentblock .inner {
z-index: 2;
position: absolute;
right: 0;
top: 0;
background: #eee;
}
.fade {
width: 100%;
height: 100%;
position: absolute;
right: 0;
top: 0;
background-color: #000;
opacity: 0;
z-index: 3;
}
.content {
height: 100%;
}
.content span {
height: 100%;
vertical-align: middle;
display: inline-block;
}
.content .spread {
vertical-align: middle;
display: inline-block;
}
#spread-1 {
color: #000;
z-index: 105;
}
#spread-2 {
z-index: 110;
}
.spread {
max-height: 800px;
max-width: 1130px;
position: relative;
}
.spread .left {
position: relative;
width: 50%;
float: left;
text-align: right;
height: 100%;
}
.spread .right {
position: relative;
width: 50%;
float: left;
text-align: left;
height: 100%;
}
div.centerimage {
overflow: hidden;
}
div.centerimage img {
max-width: 100%;
max-height: 100%;
}
div.centerimage span {
height: 100%;
vertical-align: middle;
display: inline-block;
}
div.centerimage img {
vertical-align: middle;
display: inline-block;
}
P.S. The title is really bad, don't know what I'm looking for, but please change to something more informative if you can think of anything better.

Three-Quarters of the Way to a Full Solution
This is not quite a full solution yet, as it cannot accommodate a super narrow width window size (like your old version did). However, it is a good step toward what you seek.
Here is the example.
The key things that have been changed:
Added
.spread { height: 93%; } /* You had originally wanted a height difference */
Removed
overflow: hidden from div.centerimage.
width: 50% from .left and .right.

maybe you could just pin your .spread divisor
.spread {
bottom: 11px;
left: 11px;
right: 11px;
top: 11px;
position: absolute;
/* ... */
}
This way, it will be resized the same of the viewport area.
Here a jsFiddle to demonstrate.
Carry on

I know you were probably looking for a solely CSS/HTML solution, but really you're probably best off using some Javascript. There's no way to be clean and precise just using CSS & HTML.
But if you run a tiny bit of JavaScript on page load and window-resize, then your divs can have actual height/width values and scale cleanly.
The trick is to have the outside div get its width/height set by the JavaScript, and then all its children use % dimensions so they grow appropriately.
Here's the basics using some JQuery:
<script type="text/javascript">
//Function to get the current window dimensions.
function get_window_dims() {
var dims = [];
if (parseInt(navigator.appVersion)>3) {
if (navigator.appName=="Netscape") {
dims[0] = window.innerWidth;
dims[1] = window.innerHeight;
}
if (navigator.appName.indexOf("Microsoft")!=-1) {
dims[0] = document.body.offsetWidth;
dims[1] = document.body.offsetHeight;
}
}
return dims;
}
function ResizeDivs {
var dims = get_widnow_dims();
var div_width = Math.floor(dims[0] * 0.93); // calculating the div width to be 93% of the window width
$('div.spread').css('width',div_width+'px');
}
$(function() {
ResizeDivs();
$(window).resize(function(){
ResizeDivs();
});
});
</script>
You could easily clean up this code to be more concise, but I figured I'd put it out here this way for you to see all the parts.
If you wanted to spend the extra time, you could even add more JQuery to animate the divs when the window resizes.
Hope this helps.

Have you considered using a responsive framework to solve your issue? You can set width's and heights to percentages and have min-width, min-height.

Related

Create a div with aspect ratio 1:1 knowing only its height in percentage

I was wondering if you can help me with this.
I have a div (in white) where I need to put two circular buttons (in green) on the borders. Everything should be done with CSS.
It should look like this:
Screenshot
Now, the thing is that I don't know the size of the white div, and I won't know it at the time of creation, because it will get added to the DOM afterwards. All I know is that the white div has a percentage width and height relative to its future parent. So, at the time of creation, since it's not yet added, any calls to width(), height() or its css values won't work.
I've seen all those snippets that tell you how to make a div with a fixed aspect ratio. I need this now, I need the button to be 1:1, but all I know about the dimensions, is that it has to be 100% of the height of the white div (and therefore, its width should be equal as its height). All the examples I've seen assume that you know the width and to make the height keep the ratio. In my case, what I know is the height (100%) and I want the width to adapt.
I have no idea how to achieve this.
This is my snippet:
body{
background-color: #DCDCDC;
}
.container {
width: 50%;
height: 7%;
background: white;
border-radius: 20px;
position: absolute;
}
.arrow {
background: green;
border-radius: 20px;
height: 100%;
position: absolute;
}
.arrow:after{
content: "";
display: block;
padding-right: 100%;
}
.arrow:last-child {
right: 0;
}
<div class="container">
<div class="arrow"></div>
<div class="arrow"></div>
</div>
https://jsfiddle.net/7bxecL9m/
If you know how can I do this without entering any fixed value (jQuery use is of course valid), I'd really appreciate it.
Thanks.
There are many variables here:
Since container's height is % and circle radius is px units, one is static and the other one will resize.
The only way to preserve 1:1 with just html/css, considering the container's height % will resize circle's height as well, would be to isolate circle's div width & height to something static like px units.
Now, since you said no fixed dimensions, the only thing I can think of is to comment .arrow's 100% height, to prevent resizing other than 1:1, and nesting a div inside .arrow to restrain 1:1 with static units (ideally impacting .arrow directly would be less code but if you don't want/can't set them on that element, maybe you consider this).
If you want the circle to remain circular as the content expands, you need to dynamically adjust the height to match the width. You could use Javascript to achieve this, but your border-radius is tied to container's in px static units, since container will always be bigger something like border-radius: 50% wouldn't work for both, 50% radius of circle would never match 50% of container's (that is, if you care about radius alignment).
body {
background-color: #DCDCDC;
}
body,
html {
height: 100%;
}
.container {
width: 50%;
height: 37%;
background: white;
border-radius: 20px;
position: relative;
}
.arrow {
background: green;
border-radius: 20px;
/*height: 100%;*/
position: absolute;
overflow: hidden;
}
.bLimit {
height: 40px;
width: 40px;
line-height: 40px;
}
.arrow:after {
content: "";
display: block;
padding-right: 100%;
}
.arrow:last-child {
right: 0;
}
<div class="container">
<div class="arrow">
<div class="bLimit">button overflow</div>
</div>
<div class="arrow">
<div class="bLimit">button</div>
</div>
</div>
Why not doing a fixed width in percent for your arrow :
.arrow {
background: green;
border-radius: 20px;
height: 100%;
position: absolute;
width: 10%;
}
body{
background-color: #DCDCDC;
}
.container {
width: 50%;
height: 7%;
background: white;
border-radius: 20px;
position: absolute;
}
.container:after,.container:before{
content: " ";
display: block;
padding: 4%;
z-index: 999;
top: 0;
position:absolute;
background: green;
border-radius: 50%;
}
.container:before {
left: 0;
}
.container:after{
right: 0;
}
<div class="container">
</div>
You can achieve using before and after CSS pseudo selectors. You check this Example.
There is a posibility to get this result using a image (that won't show) of the required ratio.
In this case, the ratio is 1:1 so we will use an image of 50px (but it can be any size)
.container {
width: 300px;
height: 20px;
border: solid 1px blue;
margin: 40px;
position: relative;
}
.container:nth-child(2) {
height: 40px;
}
.container:nth-child(3) {
height: 60px;
}
.arrow {
height: 100%;
background-color: red;
opacity: 0.5;
position: absolute;
border-radius: 50%;
transform: translateX(-50%);
}
.arrow:last-child {
right: 0px;
transform: translateX(50%);
}
img {
height: 100%;
opacity: 0;
}
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>
<div class="container">
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
<div class="arrow">
<img src="https://placehold.it/50x50">
</div>
</div>

How to prevent get over other divs?

I have a problem...In the following example i don't want that the div who is fixed get over the div with the background red.
Here is the example:
http://jsfiddle.net/HFjU6/3645/
#fixedContainer
{
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
}
Alright, I think I get what the OP wants. He wanted a container that stays fixed on the top of the viewport, but remains confined by a parent. This behaviour is known as a conditional sticky behaviour, and is actually implemented in both Firefox (without vendor prefix) and macOS/iOS Safari (with -webkit- prefix): see position: sticky.
Therefore the easiest (but also the least cross-browser compatible) way is simply to modify your markup, such that the sticky element stays within a parent, and you declare position: sticky on it:
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: -webkit-sticky;
position: sticky;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
transform: translate(-50%, 0); /* Negative left margins do not work with sticky */
}
#div1 {
height: 200px;
background-color: #bbb;
}
#div1 .content {
position: relative;
top: -100px; /* Top offset must be manually calculated */
}
#div2 {
height: 500px;
background-color: red;
}
<div id="div1">
<div id="fixedContainer">I am a sticky container that stays within the sticky parent</div>
<div class="content">Sticky parent</div></div>
<div id="div2">Just another element</div>
An alternative would be to use a JS-based solution. In this case, you do not actually have to modify your markup. I have changed the IDs for easier identification of the elements, however.
The gist of the logic is this:
When the scroll position does not exceed the bottom of the parent minus the outer height of the sticky content, then we do not do anything.
When the scroll position exceeds the bottom of the parent minus the outer height of the sticky content, we dynamically calculate the top position of the sticky content so that it remains visually in the parent.
$(function() {
$(window).scroll(function() {
var $c = $('#sticky-container'),
$s = $('#sticky-content'),
$t = $(this); // Short reference to window object
if ($t.scrollTop() > $c.outerHeight() - $s.outerHeight()) {
$s.css('top', $c.offset().top + $c.outerHeight() - $t.scrollTop() - $s.outerHeight());
} else {
$s.css('top', 0);
}
});
});
* {
margin: 0;
padding: 0;
}
div {
height: 500px;
background-color: red;
}
#sticky-container {
background-color: #bbb;
height: 200px;
}
#sticky-content {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
margin-left: -100px;
left: 50%;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sticky-content">Sticky content that stays within the bounds of #div1</div>
<div id="sticky-container">Sticky confinement area</div>
<div>Other content</div>
Old answer before OP clarified the question appropriately:
Just give them the appropriate z-index values. In this case, you want to:
Do not use static positioning. This can be done by using position: relative for the large elements, in conjunction with the originally position: fixed element.
Assign the appropriate stacking order. The grey <div> element to have the lowest z-index, followed by the position fixed element, and then by the red element.
There are some catchalls to stacking though: the stacking context is reset when you traverse up or down the node tree. For example, the example will not work if the elements are not siblings.
Here is a proof-of-concept example, modified from your fiddle so that inline CSS is removed.
* {
margin: 0;
padding: 0;
}
#fixedContainer {
background-color: #ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px;
z-index: 2;
}
#div1 {
height: 200px;
background-color: #bbb;
position: relative;
z-index: 1;
}
#div2 {
height: 500px;
background-color: red;
position: relative;
z-index: 3;
}
<div id="fixedContainer">z-index: 2</div>
<div id="div1">z-index: 1</div>
<div id="div2">z-index: 3</div>
Just give the z-index.
Hope it helps...
http://jsfiddle.net/HFjU6/1/#run
#fixedContainer {
background-color:#ddd;
position: fixed;
width: 200px;
height: 100px;
left: 50%;
top: 0%;
margin-left: -100px; /*half the width*/
z-index: 2;
}
.div-red {
position: relative;
z-index: 5;
}
<div id="fixedContainer"></div>
<div style="height:200px;background-color:#bbb;"></div>
<div style="height:500px;background-color:red;" class="div-red"></div>

How to make a relatively positioned child to get all parent's height

I have this layout
body, html {
height: 90%;
}
#content{
width: 100%;
height: 100%;
}
#sidebar {
position: relative;
width: 200px;
float: left;
height: 100%;
background-color: green;
}
#sidebar-content {
height: 120px;
background-color: blue;
}
#sidebar-footer {
position: absolute;
bottom: 0;
height: 50px;
width: 100%;
background-color: black;
}
#main {
position: relative;
overflow: hidden;
background-color: red;
}
#main-content {
height: 750px;
}
<div id="content">
<div id="sidebar">
<div id="sidebar-content">
</div>
<div id="sidebar-footer">
</div>
</div>
<div id="main">
<div id="main-content">
</div>
</div>
</div>
I need the sidebar to occupy all height available if it's height lower than the #main's. Setting the sidebar position to absolute solves this, but adding even more bugs, is there a solution for the relatively positioned child to get all the parent's height without specifying height of the parent in pixels?
As you can see in the fiddle, if #main exceeding the sidebar's width the sidebar is shorter, but it need to fill all the height.
CSS Flexbox does indeed solve your problem, and is the perfect answer if you don't have to support older browsers.
Basically, just adding display: flex to the container will sort this out for you.
Browsers support flexbox in a variety of ways, make sure you check the compiled CSS of that Pen to get all the browser pre-fixes and such.
Link to CodePen
You may be able to use a combination of css properties to achieve what you are looking for. The main reason you were running into trouble with the position:absolute was due to your float:left.
Have a glance through this and you may find some of the positioning and width declarations useful in your implementation:
body,
html {
height: 90%;
}
#content {
width: 100%;
height: 100%;
position: relative;
background: lightgray;
}
#sidebar {
position: absolute;
width: 200px;
height: 100%;
top: 0;
left: 0;
background-color: green;
z-index: 8;
}
#sidebar-content {
height: 120px;
background-color: blue;
}
#sidebar-footer {
position: absolute;
bottom: 0;
height: 50px;
width: 100%;
background-color: black;
}
#main {
overflow: hidden;
background-color: red;
height: 100%;
position: absolute;
top: 0;
left: 200px;
width: calc(100% - 200px);
height: 100%;
z-index: 10;
}
#main-content {}
<div id="content">
<div id="sidebar">
<div id="sidebar-content">
</div>
<div id="sidebar-footer">
</div>
</div>
<div id="main">
<div id="main-content">this is the main content
</div>
</div>
</div>
I guess jQuery solution will help you solve your problem :) Try this This will allow to have the #sidebar to have same height as the container. Hope this helps :) Happy coding.
jQuery:
$(document).ready(function(){
var wrapH = $('#content').outerHeight();
$('#sidebar').css("height", wrapH);
});
Edited:
JS Fiddle Link
$(document).ready(function(){
var wrapH = $('#main').outerHeight();
$('#sidebar').css("height", wrapH);
});
Just change the content to main. Hope this solves the issue. This will make the sidebar height be the same as the main height.

scroll the content inside the div with fixed position using browser/page scroll bar

I have some div's with position:fixed all around the page.
one of that div has little more long content.
my aim is that I want to scroll the content inside that box, using the main browser/page scroll-bar. (its not normal overflow:auto like this)
this is the exact situation
http://s7.postimage.org/d6xl1u9mz/sample.jpg
is any plugin available ?
Without knowledge of your HTML:
<body>
<section id="bodyContent"></section>
<header></header>
<section id="lSide"></section>
<section id="rSide"></section>
</body>
#bodyContent {
box-sizing: border-box;
-moz-box-sizing: border-box;
min-height: 100%;
width: 100%;
padding: 90px 45px 0px 105px;
background-clip: content-box;
background-color: #FFFFFF;
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-image: url(page_background.jpg);
background-attachment: fixed;
}
header, #lSide, #rSide {
position: fixed;
}
header {
top: 0;
width: 100%;
height: 90px;
background-image: url(page_background.jpg);
background-attachment: fixed;
}
#lSide {
left: 0;
top: 0;
height: 100%;
width: 105px;
padding: 90px 0 0 0;
}
#rSide {
right: 0;
top: 0;
height: 100%;
width: 45px;
padding: 90px 0 0 0;
}
This will force the contents of #bodyContent to sit inside the opening between the various border elements, and it will cause any overflow to trigger a scrollbar on the body element as you desire. JSFiddle
Maybe it's possible. I've created a jsFiddle which does the trick. It's not perfect, but you can develope it further... Also this snippet works only with modern browsers, but is easy to fix for older IEs too. Core code below.
JavaScript:
window.onload = function () {
var content = document.getElementById('contentwrapper'),
dimdiv = document.getElementById('scrollingheight'),
wrapHeight = document.getElementById('fixed').offsetHeight,
scroller = function () {
content.style.top = -(document.documentElement.scrollTop || document.body.scrollTop) + 5 + 'px';
return;
};
dimdiv.style.minHeight = (content.scrollHeight - wrapHeight + 2 * 5) + 'px';
window.addEventListener('scroll', scroller, false);
return;
}
CSS:
#fixed {
position: fixed;
min-width: 300px;
min-height: 200px;
max-height: 200px;
background: #fff;
left: 150px;
top: 200px;
overflow-y: hidden;
border: 1px solid #000;
}
#contentwrapper {
max-width: 290px;
position: absolute;
top: 5px;
left: 5px;
}
#scrollingheight {
position: absolute;
top: 100%;
visibility: hidden;
min-width: 1px;
}
HTML:
<div id="scrollingheight"></div>
<div id="fixed">
<div id="contentwrapper">
content
</div>
</div>
Notice, that all content in the body, but #scrollingheight, must be fixed. Constant 5 is related to #contentwrapper's top value.
AFAIK you cannot do that.
At least not without some wicked JS trickery.
Why? cause you cannot force the browser's default scrollbar height (make it smaller) to embrace some content that is inside a totally different area than the html, body (document).
My suggestion is that you build a custom scrollbar, calculate the height of your nice overflow hidden area, add it to the scrollable ratio calculation.

Vertically centered absolute position div inside relative position parent - Works in Chrome, but centers to body in Safari etc?

I am trying to vertically center some text over an image that appears on a mouseover. I have come to a solution that works with chrome (15.0.874.106) on a mac (10.7.2), but it seems to have issues in Safari (5.1.1), odd since they are both webkit based. I believe it also has the same problem in Firefox.
The text is vertically centered in relation to the parent div in chrome, but seems to center to the body or window in Safari. Am I doing something wrong or does anyone have a better solution?
jsbin: http://jsbin.com/iceroq
CSS:
.content {
width: 300px;
position: relative;
}
.content-text {
width: 100%;
height: 100%;
background: black;
position: absolute;
top: 0;
left: 0;
text-align: center;
display: none;
}
HTML:
<div class="content">
<div class="content-image">
<img src="http://placehold.it/300x500/E01B4C" />
</div>
<div class="content-text">
Google
</div>
</div>
.content-text a {
color: white;
position: relative;
top: 50%;
margin-top: -0.5em;
}
JS:
$(document).ready(function() {
$('.content').hover(
function() {
$(this).children('.content-text').show();
}, function() {
$(this).children('.content-text').hide();
});
});
I edited your jsbin: http://jsbin.com/iceroq/3
The edits were all CSS changes to .content-text a. Making the link absolutely positioned and giving it a height allows you to know what margin-top to give it (half of the height).
.content-text a {
display: block;
width: 100%;
height: 20px;
position: absolute;
top: 50%;
margin-top: -10px;
color: white;
}

Categories

Resources