Absolute CSS positioning with a top margin - javascript

I have a sidebar with some text and a footer inside it (which sticks to the bottom of the sidebar). When I resize (reduce) the window's height to e.g. half, the footer goes on top of the other texts in the sidebar. Is there a way to have a margin-top for example, so that when the window get resized, the footer keeps its position at the bottom until it is about to go on top of other elements (before it)?
.sidebar {
position: fixed;
width: 260px;
overflow-y: auto;
border-right: 1px solid #dadada;
display: inline-block;
background-color: #BDE6CA;
float: left;
z-index: 3;
}
.sidebar-content {
position: relative;
height: 100%;
width: 100%;
}
.sidebar-option {
color: #00aa4f;
font-size: 20px;
cursor: pointer;
padding: 20px 0px 20px 20px;
}
.sidebar-bottom {
bottom: 0px;
position: absolute;
width: 100%;
padding: 0px 40px 20px 0px;
text-align: right;
}
<div class="sidebar max-height">
<div class="sidebar-content">
<div class="sidebar-top">
<img class="sidebar-logo" src="http://lorempixel.com/50/50">
<div class="sidebar-option">
<img src="http://lorempixel.com/50/50">
<span>Section 1</span>
</div>
<div class="sidebar-option">
<img src="http://lorempixel.com/50/50">
<span>Section 2</span>
</div>
</div>
<div class="sidebar-bottom">
<div class="sidebar-text"><span>Sidebar footer</span>
</div>
</div>
</div>
</div>

You may add padding-bottom:40px; (example) to .sidebar-top or .sidebar-content, so there will be enough space for .sidebar-bottom

I realized this functionality cannot be done only in CSS, we need Javascript for detecting window resize and then applying CSS attributes conditionally. Since I am already using Angular.js, I prefer an Angular.js way, but the same can be done in pure Javascript or jQuery.
Using scope.$watch in a custom directive, I can detect window resize, conditionally apply CSS to the footer element (using the ng-style directive on the footer) and finally calling scope.$apply() (in my directive) to force a digest.
The "demo 3" fiddle in the first answer to this question helped a lot. Here is my fiddle. The most relevant part is applying the custom directive ("resize") and ng-style to the footer element:
<div class="sidebar-bottom" ng-style="changePosition()" resize>
<div class="sidebar-text"><span>Footer Text 1</span></div>
<div class="sidebar-text"><span>Footer Text 2</span></div>
</div>
and the directive itself and the function scope.changePosition():
app.directive('resize', function ($window) {
return function (scope, element, attr) {
var w = angular.element($window);
scope.$watch(function () {
return {
'h': window.innerHeight,
'w': window.innerWidth
};
}, function (newValue, oldValue) {
scope.changePosition = function () {
var pos ="";
if (newValue.h < 440) {
pos = "relative"
} else {
pos = "absolute"
}
return {
'position': pos
};
};
}, true);
w.bind('resize', function () {
scope.$apply();
});
}
});
And the default/initial style for the footer div:
.sidebar-bottom {
bottom: 0px;
position: absolute;
}

Related

Trying to create a div with resizable dragger

I'm pretty sure there is already an example for this but I couldn't find one, and I don't know exactly what to search for.
http://imgur.com/a/hHNkZ
I am trying to make a resizable div from the button circled in red above.
The photo behind this div comes from a slick slider ( http://kenwheeler.github.io/slick/ ).
<div class="slider-for">
<img src="images/product0.jpg" alt="">
<img src="images/product1.jpg" alt="">
<img src="images/product2.jpg" alt="">
<img src="images/product3.jpg" alt="">
</div>
I was thinking of making a width 0 div above, and then with the slider, increase its width with js maybe.
In this div, I want to put a recipe for that certain product. I have 4 photos, so the content has to change depending on picture. ( so it's not static content).
Does this need to be made in php?
I think this would be helpful to you:
https://jsfiddle.net/u0Ljnttg/1/
Its little bit complicated, but still good enough. :)
Just for sake of SO:
JS:
var links = document.getElementById("imageLinks");
links.onmousedown = function(e) {
var theSrc = e.target.dataset.src;
if (theSrc) {
str = "url(\"" + theSrc + "\");";
//Sorry for using this:
document.getElementById("imageBack").setAttribute("style", "background-image:" + str)
}
}
var resizer = document.getElementById("content-resize");
resizer.onmousedown = resizableStart;
function resizableStart(e) {
var elem = document.getElementById("content");
elem.originalW = elem.clientWidth;
this.onmousemove = resizableCheck;
this.onmouseup = this.onmouseout = resizableEnd;
}
function resizableCheck(e) {
var elem = document.getElementById("content");
if (elem.clientWidth === elem.originalW) {
elem.originalX = e.clientX;
this.onmousemove = resizableMove;
}
}
function resizableMove(e) {
var elem = document.getElementById("content");
var newW = elem.originalW - e.clientX + elem.originalX;
if (newW < elem.originalW) {
elem.style.width = newW + 'px';
}
}
function resizableEnd() {
this.onmousemove = this.onmouseout = this.onmouseup = null;
}
HTML:
<div class='container'>
<div class='images' id="imageBack" style="background-image: url('http://data.whicdn.com/images/20948152/large.png')">
<div class='content' id="content">
<div id="imageLinks">
<a href="#" data-src='http://ichef.bbci.co.uk/news/660/cpsprodpb/1325A/production/_88762487_junk_food.jpg'>1</a>
<a href="#" data-src='http://i.imgur.com/NhDejjN.jpg'>2</a>
<a href="#" data-src='https://s-media-cache-ak0.pinimg.com/564x/80/40/9d/80409d8c06d21e0c0416a40c2176def3.jpg'>3</a>
<a href="#" data-src='http://data.whicdn.com/images/20948152/large.png'>4</a>
</div>
<span id="content-resize"></span>
</div>
</div>
</div>
CSS:
html,
body {
min-height: 100% !important;
height: 100%;
}
.container {
width: 100%;
min-height: 100%;
height: 100%;
}
.images {
width: 100%;
min-height: 100% !important;
height: 100%;
}
#content {
min-height: 100% !important;
height: 100%;
/*Change this to change width*/
width: 70%;
resize: horizontal;
float: right;
position: relative;
background: white;
}
div {
border: 1px solid black;
}
span {
border: 1px solid black;
border-radius: 50%;
position: absolute;
top: calc(50% - 20px);
left: -10px;
cursor: pointer;
height: 40px;
width: 40px;
display: inline-block;
background: white;
}
I am not sure if you already solved this issue, but since you helped me on the other question, I am interested in helping you with this.
You have some options.
Use pure JavaScript. You can use a lib (eg: this) for that.
Use Jquery $().draggable() propriety. This might help for styling the button..
Using pure HTML & CSS resize. This is not good, since you cannot apply any style to the <div>.
You can make a workaround mixing three <div> elements,
One of them with position: fixed. This is your background.
Another for the container (with a width set manually to hide the page from user). Remove the scrollbar and force the width of your html, body to match your screen.
Another <div> inside the container for your content. This should be able to move horizontally to show and hide the elements.

Panels like JSFiddle

I have this,
I want,
Fiddle
When Seconds tab goes up, I want to decrease height of First Section with min First 2 showing always, same with Second section.
$('#second').resizable({
handles: {
'n': '#ngrip',
},
resize: function () {
var b = $('#second').height();
var a = $('#first').css("height", b + "px");
console.log(a.height());
}
});
Edit
Must have -- I want it to work just like JSFiddle "HTML" and "JavaScript" panels, they both are resizable but also have min heights as you can see here
http://jsfiddle.net/
$('#second').resizable({
handles: {
'n': '#ngrip',
},
maxHeight: 300,
minHeight: 150,
resize: function (event, ui) {
var h = ui.size.height;
$('#first').height(400 -h);
}
});
#main {
width:100%;
height:400px;
overflow: hidden;
position: relative;
}
#first, #second {
height:200px;
width: 100%;
overflow-y: scroll;
}
#second {
z-index:999;
position: absolute;
}
#first-head, #second-head {
background-color:red;
}
#ngrip {
position: relative;
width: 10px;
height: 10px;
background-color: #ffffff;
border: 1px solid #000000;
bottom: -5px;
left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.8.18/jquery-ui.min.js"></script>
<div id="main">
<div id="first">
<div id="first-head">
<h3>First</h3>
</div>
<div id="first-body">
<p>First-1</p>
<p>First-2</p>
<p>First-3</p>
<p>First-4</p>
<p>First-5</p>
<p>First-6</p>
</div>
</div>
<div id='second'>
<div id="second-head">
<h3>Second</h3>
<div class="ui-resizable-handle ui-resizable-n" id="ngrip"></div>
</div>
<div id="second-body">
<p>Second-1</p>
<p>Second-2</p>
<p>Second-3</p>
<p>Second-4</p>
<p>Second-5</p>
<p>Second-6</p>
</div>
</div>
</div>
Use minHeight and minHeight option of JqueryUI combined with CSS display: absolute; for #second
First, change your resize direction in HTML (from ui-resizable-s to ui-resizable-n)
<div class="ui-resizable-handle ui-resizable-n" id="ngrip"></div>
Second, use JqueryUI options in Javascript:
$('#second').resizable({
handles: {
'n': '#ngrip',
},
maxHeight: 300, // Example max height of `#second` is 300px
minHeight: 100, // Example min height of `#second` is 100px
resize: function (event, ui) {
// Get height of `#second`
var h = ui.size.height;
// Set height of `#first`
$('#first').height(400 - h); //400 is height of container `#main`
}
});
Final, change some CSS
#main {
width:100%;
height:400px;
overflow: hidden;
position: relative;
}
#first, #second {
height:200px;
width: 100%;
overflow-y: scroll;
}
#second {
z-index:999;
position: absolute;
}
#first-head, #second-head {
background-color:red;
}
#ngrip {
position: relative;
width: 10px;
height: 10px;
background-color: #ffffff;
border: 1px solid #000000;
bottom: -5px;
left: 50%;
}
Hope it help you.
Please Check this demo JS Fiddle. It will useful for you.
HTML
<div id="main">
<div id="first">
<div id="first-head">
<h3>First</h3>
</div>
<div id="first-body">
<p>First-1</p>
<p>First-2</p>
<p>First-3</p>
<p>First-4</p>
<p>First-5</p>
<p>First-6</p>
</div>
</div>
<div id='second'>
<div id="second-head">
<h3>Second</h3>
<div class="ui-resizable-handle ui-resizable-s" id="ngrip"></div>
</div>
<div id="second-body">
<p>Second-1</p>
<p>Second-2</p>
<p>Second-3</p>
<p>Second-4</p>
<p>Second-5</p>
<p>Second-6</p>
<p>Second-7</p>
<p>Second-8</p>
<p>Second-9</p>
</div>
</div>
</div>
CSS
#main {
width:100%;
height:400px;
}
#first, #second {
min-height:100px;
height:170px;
max-height:400px;
}
#second-body{
z-index:9999;
}
#first-head, #second-head {
background-color:red;
}
#first-body, #second-body {
overflow-y:auto;
height:100%;
margin-bottom:10px;
}
#ngrip {
position: absolute;
width: 10px;
height: 10px;
background-color: #ffffff;
border: 1px solid #000000;
top:0px;
left: 50%;
}
jQuery
$('#second').resizable({
handles: {
'n': '#ngrip',
},
resize: function () {
var b = $('#second').height();
var height=$('#main').height();
var a = $('#first').css("height", b + "px");
var first=$('#first').height();
$('#second').css("height",height- first+ "px");
}
});
try this below line
<div id="first" style="min-height:35%;overflow:hidden">
instead of
<div id="first">
Live Examples
Minimal Example
Full Example
Explanation
Your second comment was close to all that's required.
The "key insight" is that, in order to constrain the minimum height of one element, it suffices to constrain the maximum height of the other. If the top element cannot be taller than 250, then the bottom element cannot be any smaller than 50 (to maintain a constant container height of 300).
Relevant JavaScript
// initialise dimensions
var containerHeight = $("#container").height();
var minHeight = containerHeight * 0.30; // min 30% height
var maxHeight = containerHeight - minHeight;
// call rebalance once on page load to make sure the panels start off right
rebalance()
$("#top").resizable({
handles: 's',
maxHeight: maxHeight,
minHeight: minHeight,
resize: rebalance // whenever we resize, rebalance the panels
});
function rebalance() {
var currentTopHeight = $("#top").height();
$("#bottom").height(containerHeight - currentTopHeight);
}
I've also taken the liberty of cleaning up your code a little. I think you were having CSS problems related to filling the space after the header, and once that was fixed the resizing is fairly straightforward. I've annotated the CSS with comments to explain what's going on. You might also be interested in the discussion here: Make a div fill the height of the remaining screen space
Relevant CSS
/* both containers are full-width, and absolutely positioned in their parent */
#first, #second {
position:absolute;
width:100%;
}
/* pin the first to the top, and the second to the bottom */
#first {
top:0;
}
#second {
top:50%;
bottom:0;
}
/* The body needs to leave space at the top for the header (25px) but none at the bottom */
#first-body, #second-body {
overflow-y:auto;
width:100%;
position:absolute;
top:25px;
bottom:0;
}
I came across a plugin that looks very promising:
http://nathancahill.github.io/Split.js/
Split.js is a lightweight, unopinionated utility for creating adjustable split views or panes.
No dependencies or markup required, just two or more elements with a common parent.
Views can be split horizontally or vertically, with draggable gutters inserted between every two elements.
There is even a JS Fiddle-style Demo.
Sample JS (from demo):
Split(['#a', '#b'], {
gutterSize: 8,
cursor: 'col-resize'
})
Split(['#c', '#d'], {
direction: 'vertical',
sizes: [25, 75],
gutterSize: 8,
cursor: 'row-resize'
})
Split(['#e', '#f'], {
direction: 'vertical',
sizes: [25, 75],
gutterSize: 8,
cursor: 'row-resize'
})
Sample html usage (from demo):
<div id="a" class="split split-horizontal">
<div id="c" class="split content"></div>
<div id="d" class="split content"></div>
</div>
<div id="b" class="split split-horizontal">
<div id="e" class="split content"></div>
<div id="f" class="split content"></div>
</div>

Fixed secondary Nav bar after scrolling

I was looking through some of the posts and I found most my answer however it's still not working properly for me.
http://jsfiddle.net/5n5MA/619/
The bar you see on the jsfiddle should be catching lower than the top because there is a fixed header that will be there on my main site this secondary bar is supposed to go below it. I can get it to be fixed on jsfiddle but not on my site. And as you can see it is shrinking when it changes to fixed.
HTML:
<header>
<img class="logo" src="images/headerLogo.png">
<p class="about lighter">ABOUT US</p>
<p class="contact lighter">CONTACT US</p>
<img class="getStarted" src="images/getStarted.png">
</header>
<div class="mainSection1">
<h1>SAVE TIME & MONEY</h1>
<h2 class="lighter">CONCIERGE HAS ALL THE ANSWERS</h2>
<p>$79.99 VALUE<br>FREE FOR YOUR CLIENTS</p>
<img class="getStarted" src="images/getStarted.png">
</div>
<div class="subBar">
<p class="first">VALUE</p> <p class="second">SERVICES</p> <p class="third">BRANDS</p> <p class="fourth">HOW IT WORKS</p>
</div>
JS:
var nav = $('.subBar');
if (nav.length) {
var fixmeTop = nav.offset().top -100;
$(window).scroll(function () {
var currentScroll = $(window).scrollTop();
if (currentScroll >= fixmeTop) {
$('.subBar').css({
position: 'fixed',
width: '100%',
top: '73px',
left: '0'
});
$('header').css(
'box-shadow', 'inherit'
);
} else {
$('.subBar').css({
position: 'static'
});
$('header').css(
'box-shadow', '0px 5px 9px #515151'
);
}
});
}
css:
.subBar {
background: #F1F1F2;
height: 65px;
}
.subBar p:first-child {
margin-left: 15%;
border-left: 1px solid #bbbdc0;
}
.subBar p {
float: left;
border-right: 1px solid #bbbdc0;
width: 17%;
text-align: center;
height: 44px;
margin-top: 0px;
padding-top: 21px;
font-weight: lighter;
}
This is because the div .subBar is not given any width.
Because of this it's width get shrinked when it's position becomes fixed, taking it to be auto by default.
So specify a fixed width. It will take that width in any position.
Also, you need to have some margin on left and right so that it stays the same as you want.
You can make the following changes:
.subBar {
background: #F1F1F2;
height: 65px;
width:100%;
}
Another more accurate solution:
Change in the jquery
if (currentScroll >= fixmeTop) {
$('.subBar').css({
position: 'fixed',
top: '72px'
});
} else {
$('.subBar').css({
position: 'static',
width:'auto';
});
}
Check the FIDDLE.
Issue has been solved! I decided to make a second navbar that starts hidden than is shown when I scroll down enough. It seems to be way less jumpy and isn't taking the original bar out of the dom (which messes with other elements below it).

JavaScript Wrap Around Carousel

I am looking for some information from some front end experts on how to go about creating a custom wrap around js carousel gallery. The idea is simple really I have a carousel of images, text, or whatever and when I get to the end I want it to wrap around. I don't want the content to simply fadeIn and out to the next piece of content. This is a gallery of div's currently but suppose it's images or whatever have you.
HTML
<div id="outside-container">
<div id="inside-container" class="cf">
<div class="items" id="item1"></div>
<div class="items" id="item2"></div>
<div class="items" id="item3"></div>
<div class="items" id="item4"></div>
</div>
</div>
<div id="directions">
<h4 id="left-button">Left</h4>
<h4 id="right-button">Right</h4>
</div>
CSS
#outside-container{
display: block;
width: 400px;
height: 125px;
overflow: hidden;
border: 1px solid #000;
margin: 0px auto;
}
#inside-container{
display: block;
width: 800px;
overflow: hidden;
height: 100%;
}
.items{
float: left;
margin: 0px;
width: 200px;
height: 100%;
}
#item1{ background: green; }
#item2{ background: red; }
#item3{ background: blue; }
#item4{ background: yellow; }
#directions{
display: block;
width: 400px;
margin: 0px auto;
text-align: center;
}
#left-button, #right-button{
display: inline-block;
cursor: pointer;
margin: 10px;
}
JS
var move = 0;
$("#left-button").click(function(){
move += 200;
$("#inside-container").animate({
marginLeft: move+"px"
}, 500);
});
$("#right-button").click(function(){
move -= 200;
$("#inside-container").animate({
marginLeft: move+"px"
}, 500);
});
Here is the codepen. So to sum all this up. I am asking for a way to create an infite loop for a gallery. I have always programmed these sorts of things to come to an end and then the user has to go back the other way. If this sounds confusing follow check out the codepen. Thanks in advance.
Here you go
http://codepen.io/nickavi/pen/cpFCE
But for the love of god, please don't use jQuery animate... at least add velocity.js to it, or the GSAP plugin, you don't even have to alter your JS you just add it in and it replaces the animate function with a more efficient one.
Cheers JBSTEW
First set move to the default slider and margin reset amount:
var move = 200;
Then, set the container margin to slide left by the move amount:
var margin_reset = (move * -1) + 'px'
$("#inside-container").css('margin-left', margin_reset);
Then, adjust the animation margin slide using move variable again, and execute a function when the animation is complete that moves the last/first item to the beginning/end of the container using prepend/append.
$("#left-button").click(function(){
$("#inside-container").animate({
marginLeft: 0
}, 500, function() {
$(this).prepend( $(this).find('.items:last') )
.css('margin-left', margin_reset);
});
});
$("#right-button").click(function(){
$("#inside-container").animate({
marginLeft: (move * -2) +"px"
}, 500, function() {
$(this).append( $(this).find('.items:first') )
.css('margin-left', margin_reset);
});
});
To avoid an initial draw jump, you could change the default css #inside-container as:
#inside-container{
...
margin-left: -200px;
}
see: Codepen

edit object while animating

I am writing a small animation to a div: Flag flips when you click on it. On the click, the image has to change.
HTML:
<div id="lang"></div>
...
<div id="langnl" class="invisible">
<img id="flag" src="en.jpg" onclick="change(-1,'en')"/>
</div>
<div id="langen" class="invisible">
<img id="flag" src="nl.jpg" onclick="change(-1,'nl')"/>
</div>
CSS:
.footer #lang {
float:right;
width: 30px;
height: 20px;
text-align:center;
}
.footer #lang img {
width: 30px;
height: 20px;
margin: 0px auto;
border-radius: 5px;
}
JS:
if (!flipping) {
flipping = true;
$('#flag').animate( {
width: 0,
}, flipTime, function () {
$('#lang').html($('#lang'+lang).html());
}).animate( {
width: 30,
}, flipTime, function () {flipping = false;});
}
My observations: The first flag flip works, but does not animate the second part, because I remove #flag, and replace it. The next flips do not work, because flipping is still false.
How to solve this, and continue animating, but replacing the content of the div?
The problem was that I has two divs with the same ID, not that I was changing the div I was animating.

Categories

Resources