Resizing logo when scrolling - javascript

I have used the following code to change the size of the logo when scrolling down the page.
$(document).on('scroll', function() {
if ($(document).scrollTop() >= 10) {
$('.logo img').css('width', '50px');
} else {
$('.logo img').css('width', '');
}
});
.nav {
position: fixed top: 0;
z-index: 1;
width: 100%;
}
.nav .logo {
position: fixed;
text-align: left;
z-index: 2;
top: 0;
overflow: hidden;
opacity: .5;
}
.container {
padding-top: 120px;
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav">
<div class="logo">
<img src="http://placehold.it/100x100" alt="" />
</div>
</div>
<div class="container">
Lorem ipsum
</div>
I would like the transition to be smooth from large to small.
https://jsfiddle.net/sL89qxcx/
Is there something I can add to achieve a smooth transition?

The best way to achieve this would be to use CSS transitions, as they are hardware accelerated, and also a better separation of concerns. You can then toggle the animation by adding/removing a class in the JS.
The important part is to add both a width and transition rule to the default state of the .logo img element. You can then amend that width in the added class. Try this:
$(document).on('scroll', function() {
$('.logo img').toggleClass('small', $(document).scrollTop() >= 10);
});
.nav {
position: fixed top: 0;
z-index: 1;
width: 100%;
}
.nav .logo {
position: fixed;
text-align: left;
z-index: 2;
top: 0;
overflow: hidden;
opacity: .5;
}
.nav .logo img {
width: 100px;
transition: width 0.3s;
}
.nav .logo img.small {
width: 50px;
}
.container {
padding-top: 120px;
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="nav">
<div class="logo">
<img src="http://placehold.it/100x100" alt="" />
</div>
</div>
<div class="container">
Lorem ipsum
</div>

Some pointers for you:
Avoid setting styles using .css() as a general rule (exceptions apply, of course). Instead, consider defining a class in your CSS, eg. .small-logo {width:8%}, and use .addClass() instead.
This has the convenient side-effect that if the class is already added, it won't be added again.
In turn, this allows you to set transition: width 0.4 ease-in-out; or similar on your logo's styles. This will provide the smooth transition you're asking for.
CSS is fun!

Related

Make content overflow

I'm trying to make something where I need to duplicate all the entries (multiple times) and then later I would like to make it spin and land on a colour slowly, etc. I'm now just getting stuck at duplicating the colours, how can I make it so the new colours are overflowing, without doubling the width?
I want it so that the colours go out of the wrapper div. Now they are just distributing themselves.
Any ideas?
$(document).on("click", ".duplicate", function() {
var $wrapper = $('.wrapper .inner');
$wrapper.find('.color').each(function() {
$wrapper.append($(this).clone());
});
});
.wrapper {
width: 75%;
margin: 12px auto;
height: 26px;
border-radius: 6px;
overflow: hidden;
position: relative;
}
.wrapper .inner {
width: 100%;
height: 100%;
position: absolute;
display: flex;
}
.wrapper .color {
width: 100%;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="inner">
<div class="color" style="background:red;width:231%"></div>
<div class="color" style="background:purple;width:111%"></div>
<div class="color" style="background:orange;width:91%"></div>
</div>
</div>
<button class='duplicate'>
Duplicate
</button>
In order to have two items in the same position in document flow you need to wrap them in a parent with position:relative and give one of them position:absolute; top:0;left:0. Also note that if your element doesn't have any content, you might need to define it's height and width. To make it same size as parent, you can give it top:0;bottom:0;left:0;right:0;.
Here's a demo started from your fiddle. You might want to inspect DOM after you press "Duplicate". I made it revert to original, so you can do it multiple times.
But do note your question is currently unclear. I'm afraid you lost me at "to make it spin and land on a colour slowly". It's truly poetic, but won't get you very far on SO...
I guess you are simply over complicating this. All what you need is a reapeated linear-gradient like this:
.wrapper {
width: 75%;
margin: 12px auto;
position: relative;
}
.wrapper .inner {
width: 100%;
height: 25px;
display: flex;
border-radius: 6px;
overflow: hidden;
}
.wrapper .color {
width: 100%;
height: 100%;
}
.new {
margin-top:5px;
height:25px;
border-radius: 6px;
background-image:linear-gradient(to right,red,red 54%,purple 54%, purple 80%,orange 0);
background-size:100% 100%;
animation:change 5s linear infinite alternate;
}
#keyframes change {
from {
background-position:0 0;
}
to {
background-position:-1000px 0;
}
}
<div class="wrapper">
<div class="inner">
<div class="color" style="background:red;width:231%"></div>
<div class="color" style="background:purple;width:111%"></div>
<div class="color" style="background:orange;width:91%"></div>
</div>
<div class="new"></div>
</div>

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>

Javascript Side Content keep appearing after Toggle the Style

I'm trying to create a Side menu for my responsive website. I'm not that good with JavaScript but it is working! (so far)
My problem is that, I'm toggling the <nav> class to make it appear and dissapear from the left side. The button to click is outside the <nav> content and the button to close is a simple text inside the <nav> content.
So, my HTML looks like this:
<nav id="nav-slide" class="nav-slide">
Side Content <br>
Close
</nav>
That's the nav that I'm trying to Toggle. The button to open should be this image:
<img id="menu-icon" src="images/menu-icon.svg"/>
CSS:
.nav-slide {
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
max-width: 100%;
background-color: #3f3f3f;
z-index: 99;
box-sizing: border-box;
padding: 20px;
color:#fff;
margin-left: -100%;
transition: margin 200ms ease-in-out;
}
.nav-open {
margin-left: 0px;
transition: margin 200ms ease-in-out;
}
and my JAVASCRIPT:
$("#menu-icon").click(function(){
$("#nav-slide").toggleClass("nav-open");
});
$("#close-button").click(function(){
$("#nav-slide").toggleClass("nav-slide");
});
Is working so far! But when I click on Close text, and after closing the <nav> it keeps displaying <nav> content like this image:
Image with example of problem
Any way to solve this?
JQuerys toggleClass does add a new class to an item. If it already has that class, it will remove it from that item. So while your nav's base class is nav-slide, toggle nav-open only (not both). Here's a slightly different, basic example of an animated side-nav:
$('button').on('click', function (e) {
$('.menu').toggleClass('open');
});
html, body {
width: 100%;
height: 100%;
margin: 0;
}
.menu {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 20%;
background-color: tomato;
transform: translate(-100%, 0);
transition: transform 1s;
}
.menu.open {
transform: translate(0, 0);
}
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<button>menu</button>
<div class="menu">
<button>close</button>
</div>
Edit: Here is a pen of your example:
http://codepen.io/wilmaknattern/pen/xZXMaW

How can I add a transition for this growing div?

I am trying to add transition to a growing div.
Here is a jsfiddle: http://jsfiddle.net/fL5rLr2y/
This jsfiddle represent my real world problem.
I have the following markup:
<div class="container">
<div class="inner">
</div>
</div>
And the following css:
html, body {
height: 100%; } .container {
position: relative;
height: 80%;
background-color: blue; }
.inner {
position: absolute;
top: 30px;
left: 0;
right: 0;
height: 50px;
background-color: red; }
.inner.open {
height: initial;
bottom: 20px; }
Here is my js:
$('.inner').click(function() {
$(this).toggleClass('open');
});
I am trying to add the transition using pure css. How can I do it?
If pure css solution is not possible, how can I use js in order to solve it?
UPDATE
After a lot of investigations, it seems that using calc is the only option to do it in pure css.
Unfortunately I have bed experience with calc, especially with safari and mobile (browser crashes and other surprises). I prefer to avoid using calc for now and use javascript solution to simulate that.
Any idea how?
Edit your .inner and .inner.open classes as demonstrated below ... you need to set a predetermined height to .open
If you're going to use CSS3 transitions you can opt to use calc() to determine your .open height without compromising browser compatibility.
Check demo
.inner {
position: absolute;
top: 30px;
left: 0;
right: 0;
height: 50px;
background-color: red;
transition: height 1s;
-webkit-transition: height 1s;
-moz-transition: height 1s;
-ms-transition: height 1s;
-o-transition: height 1s;
}
.inner.open {
height: calc(100%-50px);
bottom: 20px;
}
You can use the dynamic height by updating the style below. Demo at http://jsfiddle.net/fL5rLr2y/8/
.inner {
position: absolute;
top: 30px;
left: 0;
right: 0;
height: 50px;
background-color: red;
-webkit-transition: height 1s;
transition:height 1s;
}
.inner.open {
height: calc(100% - 50px); /* top 30px + bottom 20px */
}
Or you can use jQuery animation. See the output at http://jsfiddle.net/8mn90ueb/3/ and code below
Remove the open class and the toggle type
$('.inner').click(function() {
var currentHeight = $(this).height();
if(currentHeight > 50){
currentHeight = 50;
}
else{
currentHeight = $('.container').height() - 50;
}
$(this).animate({
height:currentHeight
},1000,function(){});
});
The CSS transition property is what you need. The height calculation of .inner is now made with jQuery.
Demo with jQuery calculation
$('.inner').click(function() {
var parentHeight = $(this).parent().outerHeight() - 50; // Get parent height - 50px
var innerHeight = $(this).outerHeight(); // Get inner height
// if the inner height = 50px then change height to the parent height calculation
// otherwise return to 50 height
if (innerHeight === 50) {
$(this).height(parentHeight);
} else {
$(this).height(50);
}
});
html,
body {
height: 100%;
}
.container {
position: relative;
height: 80%;
background-color: blue;
}
.inner {
position: absolute;
top: 30px;
left: 0;
right: 0;
height: 50px;
background-color: red;
transition: height 0.5s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container">
<div class="inner"></div>
</div>
If you change your mind about calc()
The CSS transition property is what you need along with height: calc(100% - 50px) on the open class. The calc gets you a 30px gap at the top and 20px gap at the bottom when open. The bottom property has been removed.
Compatibility:
The transition property is unlikely to need browser prefixes. Have a look here for its browser support.
calc() enjoys widespread support including, importantly, IE9 + support. More information here. To provide a fallback height for IE 8 and below, provide a normal height percentage property before the calc height for older browsers to use. Something like height: 70%
Demo with CSS only
$('.inner').click(function() {
$(this).toggleClass('open');
});
html,
body {
height: 100%;
}
.container {
position: relative;
height: 80%;
background-color: blue;
}
.inner {
position: absolute;
top: 30px;
left: 0;
right: 0;
height: 50px;
background-color: red;
transition: height 0.5s;
}
.inner.open {
height: 70%; /* pick a percentage height for IE 8 and below */
height: calc(100% - 50px); /* 100% height minus 30px at the top + 20px at the bottom */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container">
<div class="inner"></div>
</div>

How do I scale this layout?

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.

Categories

Resources