How to view/hide div only in that id - javascript

I am trying to make a div where it is assigned by an id.
My goal is to make that div have two sides: the front and the back (assigned by class)
* the front is shown as default, while the back will only be shown upon user click
My question is, when trying to make a lot of this div, how can I achieve this kind of scenario, where it will only show/hide those classes only in that particular id?
<div id="user01" onclick="userId(this)">
<div class="front">
<img src="../media/media/alumni/sdc/01.jpg"> User name on front
</div>
<div class="back">
other info on back
</div>
</div>
**user01 is assigned per each user (ex.: the first user is 01, while the second is 02, and so on...)
thanks :)

Use a css class on top of your id:
<div id="user01" class="user">
Then, in your Javascript, use document.querySelectorAll along with that class:
let users = document.querySelectorAll('.user')
Now you can iterate over this DOM node collection that is returned by document.querySelectorAll and add an event listener to each one:
Array.prototype.forEach.call(users, function(user) {
user.addEventListener('click', function(event) {
/* your code to be executed on click
each user is available here as 'this' */
// example:
this.classList.toggle('active')
})
})
As mplungjan pointed out, Edge and IE don't support forEach on Node collections, so Array.prototype.forEach.call(users, function(user) ... comes in as a replacement for users.forEach(function(user) { ....
As a last step, add the CSS that flips your stuff:
.user .front {
transition: opacity .3s ease;
opacity: 1;
}
.user.active .front {
opacity: 0;
}
.user .back {
transition: opacity .3s ease;
opacity: 0;
}
.user.active .back {
opacity: 1;
}
let users = document.querySelectorAll('.user')
Array.prototype.forEach.call(users, function(user) {
user.addEventListener('click', function(event) {
/* your code to be executed on click
each user is available here as 'this' */
// example:
this.classList.toggle('active')
})
})
.user {
display: inline-block;
height: 200px;
width: 200px;
position: relative; /* this allows absolute position of children */
}
.user:hover {
cursor: pointer;
}
.user .front,
.user .back {
transition: opacity .3s ease;
color: white;
position: absolute; /* position both "sides" on top of each other */
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.user .front img,
.user .back img {
position: absolute;
z-index: 0;
}
.user .front span,
.user .back span {
background-color: rgba(0,0,0,.3);
box-shadow: 0 0 10px rgba(0,0,0,.3), 0 0 2px rgba(0,0,0,.3);
border-radius: 10px;
display: block;
left: 50%;
padding: 10px 5px;
position: absolute;
text-align: center;
top: 50%;
transform: translate(-50%, -50%);
z-index: 1;
}
.front {
opacity: 1;
}
.user.active .front {
opacity: 0;
}
.back {
background-color: #333;
opacity: 0;
}
.user.active .back {
opacity: 1;
}
<div class="user" id="user01">
<div class="front">
<img src="https://lorempixel.com/output/business-q-c-200-200-8.jpg"><span>User 1 name on front</span>
</div>
<div class="back">
other info on back for User 1
</div>
</div>
<div class="user" id="user02">
<div class="front">
<img src="https://lorempixel.com/output/business-q-c-200-200-2.jpg"><span>User 2 name on front</span>
</div>
<div class="back">
other info on back for User 2
</div>
</div>

Related

css background-image stretching on transition with different image sizes

I want my background-image with a smooth transition. When it has a different aspect-ratio predecessor. Here you'll see a example of this stretching effect.
toggle = true
jQuery(document).ready(function() {
jQuery(".button").on("click", function() {
if (toggle) {
jQuery(".test").css("background-image", "url('https://images.pexels.com/photos/4534200/pexels-photo-4534200.jpeg?cs=srgb&dl=pexels-arthouse-studio-4534200.jpg&fm=jpg')")
toggle = false
} else {
jQuery(".test").css("background-image", "url('https://images.unsplash.com/photo-1547922374-968968e3f658?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=bosco-shots-SlR66yjPsoI-unsplash.jpg')")
toggle = true
}
})
})
* {
margin: 0;
padding: 0;
}
.test {
width: 100vw;
height: 100vh;
background-image: url('https://images.unsplash.com/photo-1547922374-968968e3f658?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=bosco-shots-SlR66yjPsoI-unsplash.jpg');
transition: background-image 0.5s;
-webkit-transition: background-image 0.5s;
-o-transition: background-image 0.5s;
-moz-transition: background-image 0.5s;
-ms-transition: background-image 0.5s;
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
.button {
padding: 2px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="test">
<input class="button" type="button" value="change">
</div>
If anyone could show me an option, where I can still use background-size: cover;, and a background-image transition, it would help me a lot.
Instead of toggling the background image you can have multiple elements with a background and show the active element based on an index.
The remainder operator (%) for the (active) index makes sure we always have a valid index that never exceeds the amount of backgrounds we have.
let active = 0; // First element is active
jQuery(document).ready(function($) {
$(".button").on("click", function() {
// Update active index
active = (active + 1) % $(".bg").length;
// Show active background
$(".bg").each(function(index) {
if(index === active) {
$(this).addClass("bg-active");
}else{
$(this).removeClass("bg-active");
}
});
})
})
* {
margin: 0;
padding: 0;
}
.test {
width: 100vw;
height: 100vh;
position: relative;
}
.test > * {
position: relative; /* Make sure elements inside `.test` dont disappear behind the background(s) */
}
.bg {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
opacity: 0;
transition: opacity 0.5s;
background-position: center center;
background-size: cover;
background-repeat: no-repeat;
}
.bg-nature {
background-image: url('https://images.pexels.com/photos/4534200/pexels-photo-4534200.jpeg?cs=srgb&dl=pexels-arthouse-studio-4534200.jpg&fm=jpg');
}
.bg-art {
background-image: url('https://images.unsplash.com/photo-1547922374-968968e3f658?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=bosco-shots-SlR66yjPsoI-unsplash.jpg');
}
.bg-active {
opacity: 1;
}
.button {
padding: 2px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="test">
<div class="bg bg-nature bg-active"></div>
<div class="bg bg-art"></div>
<input class="button" type="button" value="change">
</div>

CSS transition div width from center

I am working on a little menu animation, nothing groundbreaking but just as an experiment. This is what I currently have:
HTML
<div class="menu">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
SCSS
div.menu {
width: 24px;
height: 24px;
position: relative;
margin: 48px;
cursor: pointer;
div.bar {
display: block;
width: 100%;
height: 2px;
background-color: #444;
position: absolute;
transition: all 0.25s ease-in-out;
&:nth-child(1) {
}
&:nth-child(2) {
top: 11px;
}
&:nth-child(3) {
top: 11px;
}
&:nth-child(4) {
bottom: 0;
}
}
&.active {
div.bar {
&:nth-child(1) {
width: 0;
}
&:nth-child(2) {
transform: rotate(-45deg);
}
&:nth-child(3) {
transform: rotate(45deg);
}
&:nth-child(4) {
width: 0;
}
}
}
}
JAVASCRIPT
var menu = document.querySelector('.menu');
menu.addEventListener('click', function(){
menu.classList.toggle('active');
});
And this is a pen of it in action:
https://codepen.io/mikehdesign/pen/eWJKKN
Currently, when the menu is active the top and bottom div.bar reduce their width to 0 to the left. I would like to adjust this so they reduce their width to the center. I have tried messing with margins for them but had no luck, if anyone could shed some light or suggest a different approach if needed that would be great.
Mike
You can use transform-origin to do this:
with respect to your dimensions it would be 12px up and down(+ and -) as in the code below:
&.active {
div.bar {
&:nth-child(1) {
transform-origin:12px 12px;
transform: scale(0);
}
&:nth-child(2) {
transform: rotate(-45deg);
}
&:nth-child(3) {
transform: rotate(45deg);
}
&:nth-child(4) {
transform-origin:12px -12px;
transform: scale(0);
}
}
}
Check this out: JsFiddle Link
I would use the pseudo elements to split up the transform animation.
Demo (no script version)
HTML (note only three bars)
<input type="checkbox" id="toggle-menu" hidden>
<label for="toggle-menu" class="menu">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</label>
SCSS
// two step transition
// as translate and rotation can't (yet) be animated individually
// we use the pseudo elements to split up the animation
//
// - bar elements will handle the vertical transform
// - :after elements will handle rotation/scale
// variables to control transition time and delay
$transition-time: 300ms;
$transition-delay: 300ms;
.menu {
width: 24px;
height: 24px;
position: relative;
cursor: pointer;
display: block;
}
.bar {
height: 2px;
position: absolute;
top: 50%;
width:100%;
// Entering `hamburger` state
// 1) add a delay on bars to wait for the :after elements to rotate/scale back
// 2) the :after elements have no delay
transition: $transition-time $transition-delay; // 1
&:after {
content:'';
display:table;
background: black;
position: inherit; width: inherit; height:inherit;
transition: $transition-time; // 2
}
// transform the bars into hamburger
&:nth-child(1){ transform: translateY(-8px); }
&:nth-child(3){ transform: translateY(8px);}
}
// when toggle-menu checkbox is checked transform to `X`
[id="toggle-menu"]:checked ~ .menu {
.bar {
// Entering `X` state
// 1) to animate bars to the center we simply remove the transform
// 2) as we are now animating backwards we switch the transition
// on the bars and their :after elements
transform: none; // 1
transition: $transition-time; // 2
&:after { transition: $transition-time $transition-delay } // 2
// rotate the top and bottom :after elements
&:nth-child(1):after{ transform: rotate(-45deg); }
&:nth-child(3):after{ transform: rotate(45deg);}
// hide the middle :after by scaling to zero
// (when all bars are at the center)
&:nth-child(2):after{ transform: scale(0); }
}
}

Hard transition of other properties when display property is involved

I want to fade between two differently sized elements within a container overlaying each other. The first element should be faded out, then the container resized and finally the other element faded in.
Here's the related snippet:
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
function switchLayers() {
layer1.addEventListener("transitionend", function() {
layer2.classList.add("fadein");
});
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px;
overflow: hidden;
}
.layer {
position: relative;
width: 400px;
}
#layer1 {
height: 100px;
float: left;
background-color: blue;
}
#layer2 {
height: 150px;
background-color: red;
display: none;
opacity: 0;
}
#layer1.fadeout {
opacity: 0;
transition: opacity 1s ease-out;
}
#layer2.fadein {
display: block;
opacity: 1;
transition: opacity 1s ease-out;
}
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>
When the second layer's display property is set to block it works as expected, i.e. the opacity is changed from 0 to 1 within a second. Though if it's set to none, the transition suddenly is discrete.
I've tried to set all within the transition value to transition all properties and also tried to include the display property in the transition like this:
transition: display 0s, opacity 1s ease-out;
Though without success. Note that because the container should resize to the size of the currently displayed layer, the visibility property can't be used (as it hides the element but still lets it occupy the space).
How to made this work?
Try using the visibility property instead of display.
For more information regarding the state changes in visibility and display, refer article.
For transitioning the parent height, you have to manually change the height property of the #container. Using display: block & display: none will never transition the parent.
Refer code:
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
function switchLayers() {
layer1.addEventListener("transitionend", function() {
layer2.classList.add("fadein");
document.getElementById("container").style.height = "170px";
});
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px;
height: 100px;
overflow: hidden;
transition: all 0.5s;
}
.layer {
position: relative;
width: 400px;
}
#layer1 {
height: 100px;
float: left;
background-color: blue;
}
#layer2 {
height: 150px;
background-color: red;
visibility: none;
opacity: 0;
}
#layer1.fadeout {
visibility: none;
opacity: 0;
transition: all 1s ease-out;
}
#layer2.fadein {
visibility: visible;
opacity: 1;
transition: all 1s ease-out;
}
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>
There is no straightforward way. Transitions do not work on display, nor do they work on auto height. So, visibility is a good bet.
Note that because the container should resize to the size of the
currently displayed layer, the visibility property can't be used (as
it hides the element but still lets it occupy the space).
Then, you will need to hack it out. You can make use of min-height. Give a faux min-height to your container, and then apply the height of your layer2 to it once the transition ends. Also, because display on layer2 will block the transition, you need to separate out the classes for display and opacity and space out their application using a zero timeout in between.
Here is a crude idea:
var layer1 = document.getElementById("layer1"),
layer2 = document.getElementById("layer2"),
container = document.getElementById("container"),
h = window.getComputedStyle(layer2).getPropertyValue("height");
container.addEventListener("transitionend", function(e) {
if (e.target.id === 'layer1') {
// apply layer2 height to container min-height
container.style.minHeight = h;
}
if (e.target.id === 'container') {
// First show the layer2
layer2.classList.add("show");
// Then a dummy pause to fadein
setTimeout(function(){
layer2.classList.add("fadein");
}, 0);
}
}, false);
function switchLayers() {
layer1.classList.add("fadeout");
}
#container {
position: relative;
background-color: yellow;
padding: 10px; overflow: hidden;
min-height: 1px; /* faux min-height */
transition: min-height 1s linear;
}
.layer { position: relative; width: 400px; }
#layer1 {
height: 100px; float: left;
background-color: blue;
transition: all 1s linear;
}
#layer2 {
height: 150px; background-color: red;
display: none; opacity: 0;
transition: opacity 1s linear;
}
#layer1.fadeout { opacity: 0; }
#layer2.show { display: block; } /* Separate out display */
#layer2.fadein { opacity: 1; } /* Separate out opacity */
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
<div id="layer1" class="layer"></div>
<div id="layer2" class="layer"></div>
</div>

automatic cookie bar pure css works fine but need delay

I added this pure css cookie bar to my website and all works fine, the only problem is that when you enter in the site, you can see FIRST the cookie bar, AND the cookie bar go up and go down at the end.
How can see my cookie bar only go down when i enter in my site, i thought to change de thenimation delay, add set time out .... but nothing change !!
here is the original codepen and you can see what i want to change in it
www.codepen.io/natewiley/pen/uGtcD
HERE IS MY CODE
<input class="checkbox-cb" id="checkbox-cb" type="checkbox" />
<div class="cookie-bar">
<div class="message">
This website uses cookies to give you an incredible experience. By using
this website you agree to the
<div class="buttoncookies-container">
<a style="letter-spacing: 1px;" class="buttoncookies" id="modalcookieslinken" onclick="toggleOverlay()">terms</a>
</div>
</div>
<div class="mobile">
This website uses cookies,
<div class="buttoncookies-container">
<a style="letter-spacing: 1px;" class="buttoncookies" id="modalcookiesshortlink" onclick="toggleOverlay()">
learn more
</a>
</div>
</div>
<label for="checkbox-cb" class="close-cb">X</label>
</div>
</div>
HERE IS MY CSS
.cookie-bar { z-index:9996; position: fixed; width: 100%; top: 0; right: 0; left: 0; height: auto; padding: 20px; line-height:20px; text-align: center; background: #d2c6af; transition: .8s; animation: slideIn .8s; animation-delay: .8s; display: inline-block; }
.mobile { display: none; }
#keyframes slideIn { 0% { transform: translateY(-1000px); } 100% { transform: translateY(0); } }
.close-cb { border: none; background: none; position: absolute; display: inline-block; right: 20px; top: 10px; cursor: pointer; }
.close-cb:hover { color:#fff;; }
.checkbox-cb { display: none;}
#checkbox-cb:checked + .cookie-bar { transform: translateY(-1000px); }
Removing the line in css
animation-delay: .8s;
will give you the result
Make the animation last longer.
animation: slideIn 4s;
Plus add some trick to animation flow:
0% {
transform: translateY(-50px);
}
50% {
transform: translateY(-50px);
}
100% {
transform: translateY(0);
}

The easiest way to change text with flip effect

I am looking for simple way to flip text.
For example I have currently "Hello" text in tag, and I need to flip it to "world", only once , I don't need to flip it back to "Hello", even if sometimes need I don't really need to save previous state. Just pass new text string and it should flip older to newer one.
I know that there are a lot of libraries like https://github.com/daynin/wodry , but for this I need to provide span inside it with specific style, and hardcode all possible flip text strings. I don't need specific part of the text, I need to flip it all at once.
Please suggest the best way to implement this.
Without using span, here is an example of what you are trying to achieve
- from Hello to word, without going back ( you can adjust it later to your needs: height, colour, width and the other attributes)
HTML:
<div class="flip">
<div class="item">
<div class="face front">Hello</div>
<div class="face back">word</div>
</div>
</div>
CSS:
.flip {
-webkit-perspective: 300;
width: 400px;
height: 200px;
}
.flip .item.flipped {
-webkit-transform: rotatex(-180deg);
}
.flip .item {
width: 100%;
height: 100%;
-webkit-transform-style: preserve-3d;
-webkit-transition: 0.5s;
}
.flip .item .face {
width: 100%;
height: 100%;
position: absolute;
-webkit-backface-visibility: hidden ;
z-index: 2;
text-align: center;
line-height: 200px;
}
.flip .item .front {
position: absolute;
z-index: 1;
background: black;
color: white;
cursor: pointer;
}
.flip .item .back {
-webkit-transform: rotatex(-180deg);
background-color: green;
color: black;
}
and a little JS to make it functional:
$('.flip').click(function () {
$(this).find('.item').addClass('flipped');
});
fiddle url: http://jsfiddle.net/GDdtS/9909/

Categories