Strange CSS transition behavior on adding class - javascript

Class Event 1 is what I am trying to achieve by just placing class directly and not adding hover properties, though it's working for Hover Elements.
Please check this pen and you can find the problem by following the below instructions:
Type anything in the "Name"
Click Tab
You should reach the 1st State(Orange border on left and bottom and some transition effect), in which it pulls itself from the right corner, I don't understand why it's doing that. It working completely perfect in the Hover Example which is referenced above as well.
Understanding of my CSS
.draw {
transition: color 0.25s;
It gives an imaginary border of 2px transparent, which we will highlight later
&::before,
&::after {
border: 2px solid transparent;
width: 0;
height: 0;
}
This is where you start the transition of ::before from top-left corner
/* This covers the top & right borders (expands right, then down) */
&::before {
top: 0;
left:0;
}
This will change the color of the text.
&.dj {
color: rgb(255,123,0);
}
Here I want to expand it till 66% width.
/* Class styles */
&.dj::before,
&.dj::after {
width: 66%;
height: 100%;
}
Is it mandatory to add/recommended ::after?
&.dj::before {
border-bottom-color: rgb(255,123,0);
border-left-color: rgb(255,123,0); // Make borders visible
transition:
height 0s ease-out, // Width expands first
width 0.25s ease-out; // And then height
}
}

I can see a couple of differences between your hover demo and your tab implementation.
The first is that in the hover demo a left border is applied to .draw:before and a bottom border to .draw:after. In your tab implementation both borders are applied to .draw:after, and since .draw:after is aligned to the bottom of the button this messes up the vertical animation, which you actually want to start from the top and animate in a downward direction. This is fixed by giving .draw:after top:0 instead of bottom:0.
The second problem is that you are applying the .draw and .dj classes simultaneously. As a consequence the border width and height is applied immediately. What you need to do is toggle between the width height start and end values. I suggest applying the .draw class directly to the button in your markup, and instead of toggling both classes, only toggle the .dj class when the user tabs.
Here is a forked pen with these changes applied: https://codepen.io/jnicol/pen/EbNavz
There are various other enhancements that could be made, but those changes should fix the immediate problem you have described.

Related

Specific CSS rules for overlapping shapes/divs

I'm trying to recreate a screenshot app to better understand HTML, CSS and Electron and so far I've made a keybind that toggles the overlay of a 0.25 opacity transparent box that fills the screen. And a transparent red outlined box that can be dragged to select an area for the screenshot
As the red box is transparent and is on top of the 0.25 opacity box that fills the screen, the red box has the same opacity as the rest of the screen. I want the area inside the red box to "clear the opacity" so that it is viewed as 0.0 opacity, basically a "bright area" in the red box that looks the same as the screen would without the opacity. Like this
I tried setting the rgba to (0,0,0,0) but that didn't change anything as I expected and I cannot find any documentation for CSS about overlapping elements.
Do you have any idea on how I can implement this?
The first thing that comes to mind for me is a huge box shadow on a transparent element. I don't know how performant this is, but it works.
.screenshot {
position: fixed;
top: 50px;
left: 50px;
width: 300px;
height: 100px;
border: 1px solid red;
/* large box shadow */
box-shadow: 0 0 0 max(100vw, 100vh) #0005;
}
<div class='screenshot'></div>

CSS transition property does not take effect on div

This is my first question on stack exchange so feel free to let me know if I haven't included enough information. I've looked for a solution to my particular issue and found nothing relevant so here goes...
I'm trying to achieve a sidebar navigation that slides in upon a menu button being pressed. The rest of the page should slide with it so it flows smoothly. I have used some simple javascript to toggle on/off a .active class for the navigation sidebar div and the content-wrap div. For reference, this is what I'm trying to do: http://antrikshy.com/. The transition property is applied to both the sidebar div and content-wrap element but is only affecting the navigation bar. After inspecting the webpage, I can see the css properties have been applied to the content-wrap element successfully, but they don't work. This has been tested in safari and firefox with no change in results.
See the Pen sidebar transition example on CodePen.
Here is the individual css on the content-wrap:
.content-wrap {
position: relative;
transition: all ease 2.5s;
padding: 10px;
overflow: auto;
}
You need to define both sides of the transition. If you are transitioning on left you need the left attribute of 0 so the transition has a starting point.
.content-wrap {
position: relative;
transition: all ease 2.5s;
padding: 10px;
overflow: auto;
left:0 /* THIS */
}
On my browser that fixes your pen -- https://codepen.io/anon/pen/EvKQxR.

Position: sticky - scroll bouncing when combined with javascript height adjustment

After playing with position: sticky for a while, I started implementing it for sticky navigation and ran into this interesting, but frustrating scroll bouncing issue.
This is a common type of navigation behaviour seen on many sites, where you would traditionally use javascript to calculate offsets to a relative element in the page. When the element reaches the top of the window, a 'stuck' class would be added, taking the element out of the document flow with position: fixed, and a dummy element of the same height would be added in it's place to prevent the page from 'jumping'. Additionally, it's common to see javascript then shrink the height of that navigation to save space while scrolling.
CSS now seemingly takes care of all this with position: sticky, apart from (as far as I can tell), detecting when the element is 'stuck'. Instead I used some javascript to do the stuck detection, discovering that everything works great, right up until the height of the sticky element needs to change.
It's pretty hard to explain, but it wreaks havoc in production - so here's a stripped down example I've made to illustrate the issue as simply as possible.
CSS sticky position height adjustment bug
It's best illustrated when the height of the page is just the right length, so I've set a fixed height on the element to make sure everyone is able to see the same thing. You can add more content and it's still an issue when scrolling past.
The result is some really weird behaviour. When scrolling down, the navigation sticks, and as it shrinks the navbar, the 'dummy element' the browser is automatically creating courtesy of position: sticky seems to be kept in sync with it. That means, when the stuck class is added, the whole page gets smaller, and a fraction of a second later, the navigation is no longer stuck, thus resulting in a glitchy vibration loop.
The behaviour is also completely different across every browser I've tested. In chrome, this bouncing can never be resolved, it stays in the infinite loop constantly adding / removing the stuck class. More interestingly in Safari, the scroll position is 'pushed back' to a state where it wont bug out. Then in Firefox, it does both of these, glitching for a second or two, before forcing the scroll position back up again.
I'm wondering if anyone has experienced this, and come up with any solutions? Any js workaround I've come up with hasn't really worked or been very good! Surely as popularity grows, more people are going to hit this one...
Genius workarounds, hacks, insights, or perfect solutions all welcome!
Try adding overflow-anchor: none; to the sticky element when applying changes that would alter its size (and potentially affect window size/element positioning).
Update: ultimately, the right solution I've hit on is: have an outer element that NEVER changes size (it's always the same full height at any given breakpoint). That one is made sticky. But it also should have no background/visual styles, and it's effective height should be defined by height + bottom margin (so that it takes up the right amount of initial space in the document, but doesn't actually block clicks once the visual nav shrinks and gives more space.
Then have an inner element that does change size, either in reality or just visually.
You can also use modern properties like contain: layout size; on the inner element like
(Apparently you need more reputation to comment than answer ...)
This seems like a legitimate layout bug, so I'm curious what the opinion of browser contributors might be. Raised issues in the Chromium and Firefox bug trackers to see what'll happen:
https://bugs.chromium.org/p/chromium/issues/detail?id=734461
https://bugzilla.mozilla.org/show_bug.cgi?id=1374171
I can confirm this is a problem after attempting the same thing. I'm using position sticky on my header and adding a class at the same time via JS (to trigger some animations which change height as the CodePen's above describe)
var header = document.getElementById("header");
var sticky = header.offsetTop;
window.onscroll = function () {
if (window.scrollY > sticky) {
header.classList.add("stuck");
} else {
header.classList.remove("stuck");
}
};
The height change does in fact mess with the window height and as it becomes 1px smaller will trigger the else which removes my animation. Removing the animation changes the height back to the original size and the loop starts again.
I'd like to know how to code this correctly without a native stuck element/class/pseudo
I forked your pen.
Here is one workaround I came up with that visually gives the same effect.
It appears that transitioning a transform instead of height along with position: sticky works just fine. You don't get the constant class toggling.
So if we want to halve the height of our nav, we can squish it in half by changing scaleY from 1 to 0.5
This in turns squishes our links, so we then scale those up to double their original size to offset the squishing, adjusting scaleY from 1 to 2.
The last fix we have to do is translating the nav up to the top of the page to compensate for the smaller height.
Snippet is below. The key parts here are as follows:
nav {
transform: scaleY(1) translateY(0);
}
nav a {
transform: scaleY(1);
}
nav.stuck {
transform: scaleY(0.5) translateY(-50%);
}
nav.stuck a {
transform: scaleY(2);
}
nav, nav a {
transition: all 0.6 ease-in-out;
}
The first two rules are not strictly necessary, but I like to include a before and after just to make things extra clear.
nav = document.querySelector('nav');
section = document.querySelector('section');
function supportSticky() {
if(window.CSS && CSS.supports) {
return CSS.supports("(position: sticky)") || CSS.supports("(position: -webkit-sticky)");
} else {
var el = document.createElement("div");
el.style.position = "sticky";
return el.style.position == "sticky";
}
}
function handleScroll() {
function isStuck(el) {
return el.offsetTop - section.scrollTop <= 0 ? true : false;
}
isStuck(nav) ? nav.classList.add("stuck") : nav.classList.remove("stuck");
}
if (supportSticky()) section.addEventListener('scroll', handleScroll);
html,
body,
h1 {
margin: 0;
font-family: arial;
}
section {
width: 100%;
max-width: 600px;
margin: 0px auto;
box-shadow: 0 1px 7px #ccc;
height: 378px;
overflow-y: scroll;
}
header {
padding: 3em;
}
nav {
display: flex;
width: 100%;
background-color: #ddd;
justify-content: center;
padding: 3em;
box-sizing: border-box;
position: sticky;
top: 0;
transition: all .6s ease-in-out;
transform: scaleY(1) translateY(0);
}
nav.stuck {
background-color: red;
transform: scaleY(0.5) translateY(-50%);
}
nav.stuck a {
transform: scaleY(2);
}
nav a {
text-decoration: none;
color: #fff;
padding: 1ch 1em;
background-color: #bbb;
margin-right: 1em;
border-radius: 3px;
transition: all .6s ease-in-out;
}
nav a:hover {
background-color: #aaa;
}
article {
padding: 3em;
}
<section>
<header>
<h1>CSS sticky position height adjustment bug</h1>
</header>
<nav>
Item 1
Item 2
Item 3
Item 4
</nav>
<article>
<h1>Sticky navigation</h1>
<p>The navigation above should shrink when it gets to the top.</p>
<h1>There is no 'stuck feature' in CSS</h1>
<p>So we need javascript to work that out, and set a stuck class.</p>
<h1>But it bounces!</h1>
<p>Because the dummy element is kept in sync with the nav height...</p>
</article>
</section>
This was driving me mad for a while, but (based on solution from This question/answer) a good solution is to create an additional external element that is the sticky one which never changes size, and then have the internal element change size/position within that container as needed.
An example fiddle I made with an observer to detect when 'stuck' (could also use scroll offset if there's just a fixed-size element above it):
https://jsfiddle.net/ccarnage/fveyc6nL/24/
Summary is:
<div id="sticky-container" style="height:100px;">
<div id="header-contents-shrinkable">
...
</div>
</div>
Where #header-contents-shrinkable will have its style changed when the sticky-container is stuck to the top of the page (e.g. height reduced)

Set scroll position back after changing element position fixed and unfixed

I have a JSBin with a page, and a functional sliding nav. The only thing wrong with it is that it resets the scroll position when I open the side navigation. I use a jquery click event to toggle the nav and move the page to the side. When it moves the page over, it sets the position fixed, and moves it over 200 px. I have tried to use jquery to record the scroll position before the nav is toggled, and set it back when it isn't fixed, but after trying to use other examples, they won't work. I don't know if there is something wrong with my script, or I could use css another way.
The JSBin is here
I would like to not introduce anything but html, css, js, or jquery in the answer.
This worked for me:
Javascript:
$('.c-hamburger').click(function(){
if($('.nav').css('width') == '0px'){
$('.nav').css('width', '200px');
$('.body').css('margin-left', '200px');
}else{
$('.nav').css('width', '0px');
$('.body').css('margin-left', '0px');
}
});
CSS:
.nav{
width: 0px;
transition: width 0.5s;
overflow: hidden;
}
.body{
transition: margin-left 0.5s;
}
center{
min-width: 200px;
}

Set opacity on background-image with media query

I have a couple of divs, each with a background image. I'm using responsive and adaptive CSS, and when my divs' widths gets less than a certain size(760px btw), the text and some tables with styling becomes hard to read/see with the background image moving in behind them(the background image is on the far right of the text/tables and unobtrusive if the width is above 760px...). So when the width of the viewport gets to 760px and less, I only want the background image to have an opacity...
How do I do that?
So my CSS starts like this:
#media screen and (max-width: 760px){
background: #cdcdcd url("/images/back.jpg") no-repeat top right;
/*How do I set the opacity of only the background?*/
}
You can not change the opacity of a background image, unless you move it to a separate container.
All you can change is the opacity of BG color using rgba():
background: rgba(0, 0, 0, .5);
You can't set opacity just for a background, but the whole element. You can set opacity of background color (see Zoltan's answer for the example).
You can set white <div> over the image and change it's opacity.
<div class="yourImage">
<div class="imageCover"></div>
</div>
.yourImage {
background: url(http://blog.stackoverflow.com/wp-content/uploads/stackoverflow-logo-300.png);
width: 300px;
height: 83px;
}
.imageCover {
background: #fff;
width: 300px;
height: 83px;
opacity: .5;
}
Live demo: Tinkerbin
However, this won't work if you don't have a clean background BEHIND your image.

Categories

Resources