Given two rows of cards, I'm trying to combine the following animations:
Move the first card on the first row over the second card on the second row.
This is done by changing the top and left style properties.
Flip the first card on the first row.
I'm flipping the card based on this w3schools example.
Move the second card on the first row to the left.
The card is moved to the left by giving the div next to it zero width.
Animation 3) seems to conflict with animation 2).
Normally, a 'flip' involves swapping the front facing div with the back facing div.
However, when animation 3) gives the parent div zero width, the front and back are no longer aligned and both sides can be seen.
The following snippet demonstrates that a 'flip' seems to work, while 'move and flip' goes wrong.
Can you help me fix this such that all animations work correctly together?
function flipCard() {
const flipCard = document.querySelector('.top .flip-card')
const rect = flipCard.getBoundingClientRect()
flipCard.classList.add('moving')
flipCard.classList.add('flipped')
return [flipCard, rect]
}
function moveFlipCard() {
const srcSleeve = document.querySelector('.top .sleeve')
srcSleeve.classList.add('closed')
const [srcFlipCard, srcRect] = flipCard()
const targetFlipCard = document.querySelectorAll('.bottom .sleeve')[1]
const targetRect = targetFlipCard.getBoundingClientRect()
const offset = {
top: targetRect.top - srcRect.top,
left: targetRect.left - srcRect.left,
}
srcFlipCard.style.top = offset.top + 'px'
srcFlipCard.style.left = offset.left + 'px'
}
const flipButton = document.getElementById('flipCard')
flipButton.addEventListener('click', flipCard)
const moveFlipButton = document.getElementById('moveFlipCard')
moveFlipButton.addEventListener('click', moveFlipCard)
* {
font-family: sans-serif;
font-size: 24px;
}
.cards {
display: flex;
position: relative;
}
.sleeve {
position: relative;
width: 60px;
height: 76px;
transition: width 1s;
}
.sleeve.closed {
width: 0;
}
.card {
position: relative;
width: 50px;
height: 70px;
border: 3px solid black;
border-radius: 5px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
font-size: 24px;
margin: 0 2px;
transition: top 1s, left 1s;
}
.card.closed {
background-color: rgb(125, 171, 250);
color: black;
}
.card.open {
background-color: rgb(218, 218, 218);
}
.card.black {
color: black;
}
.card.red {
color: red;
}
/* Based on https://www.w3schools.com/howto/howto_css_flip_card.asp */
.flip-card {
position: relative;
perspective: 1000px;
transition: top 1s, left 1s;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 1s;
transform-style: preserve-3d;
}
.flip-card.flipped .flip-card-inner {
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flip-card-back {
transform: rotateY(180deg);
}
.flip-card.moving {
z-index: 1;
}
<div id="app">
<div class="top cards">
<div class="sleeve">
<div class="flip-card" style="top: 0; left: 0;">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open black">A♣</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
<div class="sleeve">
<div class="flip-card" style="top: 0; left: 0;">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open black">2♣</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottom cards">
<div class="sleeve">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open red">5♥</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
<div class="sleeve">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open red">6♥</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
</div>
<button id="flipCard">flip</button>
<button id="moveFlipCard">move and flip</button>
</div>
TLDR: To solve this, I explicitly set transform-origin: 30px 0 0. Now the point around which a transformation is applied no longer depends on the size of the bounding box.
I now see where it goes wrong. The problem lies with the transform-origin.
The transform origin is the point around which a transformation is applied.
For animation 2) this corresponds to the point around which the card is rotated 180 degrees over the y-axis (transform: rotateY(180deg)).
The default value of the transform-origin property is 50% 50% 0, where the values correspond to the offset over the x-axis, y-axis and z-axis, respectively.
However, what does 50% mean? 50% of what?
Percentages refer to the size of bounding box
So, what's the bounding box of the flipped div? When I inspect <div class="flip-card-inner"> I see it has a dimensions 60x0:
where 60 corresponds to width: 60px of parent <div class="sleeve">.
So for <div class="flip-card-inner"> the default transform-origin is 30px 0 0. This is what I expect: the card rotates over its y-axis at a point that lies halfway over the x-axis, such that the card is in the same location when flipped.
Now let's see what happens when we apply animation 3), i.e. move the second card on the first row to the left by giving the div next to it zero width:
Now the bounding box is 0x0, because the parent <div class="sleeve closed"> has zero width. Since the bounding box has changed, so has the transform-origin: 50% of 0 is 0, so we get 0 0 0. The card now rotates over its y-axis at a point that lies on the left side of the card. This has the undesired effect that the flipped card does not end up at the same location as where it started.
To solve this, I explicitly set transform-origin: 30px 0 0. Now the point around which a transformation is applied no longer depends on the size of the bounding box.
Working example:
function flipCard() {
const flipCard = document.querySelector('.top .flip-card')
const rect = flipCard.getBoundingClientRect()
flipCard.classList.add('moving')
flipCard.classList.add('flipped')
return [flipCard, rect]
}
function moveFlipCard() {
const srcSleeve = document.querySelector('.top .sleeve')
srcSleeve.classList.add('closed')
const [srcFlipCard, srcRect] = flipCard()
const targetFlipCard = document.querySelectorAll('.bottom .sleeve')[1]
const targetRect = targetFlipCard.getBoundingClientRect()
const offset = {
top: targetRect.top - srcRect.top,
left: targetRect.left - srcRect.left,
}
srcFlipCard.style.top = offset.top + 'px'
srcFlipCard.style.left = offset.left + 'px'
}
const flipButton = document.getElementById('flipCard')
flipButton.addEventListener('click', flipCard)
const moveFlipButton = document.getElementById('moveFlipCard')
moveFlipButton.addEventListener('click', moveFlipCard)
* {
font-family: sans-serif;
font-size: 24px;
}
.cards {
display: flex;
position: relative;
}
.sleeve {
position: relative;
width: 60px;
height: 76px;
transition: width 1s;
}
.sleeve.closed {
width: 0;
}
.card {
position: relative;
width: 50px;
height: 70px;
border: 3px solid black;
border-radius: 5px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
font-size: 24px;
margin: 0 2px;
transition: top 1s, left 1s;
}
.card.closed {
background-color: rgb(125, 171, 250);
color: black;
}
.card.open {
background-color: rgb(218, 218, 218);
}
.card.black {
color: black;
}
.card.red {
color: red;
}
/* Based on https://www.w3schools.com/howto/howto_css_flip_card.asp */
.flip-card {
position: relative;
perspective: 1000px;
transition: top 1s, left 1s;
}
.flip-card-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 1s;
transform-style: preserve-3d;
}
.flip-card.flipped .flip-card-inner {
transform-origin: 30px 0 0;
transform: rotateY(180deg);
}
.flip-card-front,
.flip-card-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
}
.flip-card-back {
transform-origin: 30px 0 0;
transform: rotateY(180deg);
}
.flip-card.moving {
z-index: 1;
}
<div id="app">
<div class="top cards">
<div class="sleeve">
<div class="flip-card" style="top: 0; left: 0;">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open black">A♣</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
<div class="sleeve">
<div class="flip-card" style="top: 0; left: 0;">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open black">2♣</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottom cards">
<div class="sleeve">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open red">5♥</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
<div class="sleeve">
<div class="flip-card">
<div class="flip-card-inner">
<div class="flip-card-front">
<div class="card open red">6♥</div>
</div>
<div class="flip-card-back">
<div class="card closed">?</div>
</div>
</div>
</div>
</div>
</div>
<button id="flipCard">flip</button>
<button id="moveFlipCard">move and flip</button>
</div>
Related
Hello guys I want my animation be infinite and when it finish - he restart without any jump space.
and moreover allow to click event to go next position on my animation circle
How can I apply it?
let jump = 0;
let index = 0;
const boxContainer = document.querySelector(".boxContainer");
const animate = () => {
boxContainer.style.transform = `translate(${jump}px)`;
boxContainer.appendChild(boxContainer.children[index].cloneNode(true));
index++;
};
const nextBox = () => {
jump -= 100;
requestAnimationFrame(animate);
};
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.container {
background-color: aqua;
height: fit-content;
width: 500px;
overflow-x: hidden;
position: relative;
}
.anim {
animation: anim 10s infinite linear;
}
.boxContainer {
display: flex;
transition: transform 0.2s;
}
.boxContainer > .box {
width: 90px;
height: 90px;
margin: 5px;
background-color: blue;
flex-shrink: 0;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.container > button {
position: absolute;
left: 0px;
top: 32px;
width: 50px;
}
#keyframes anim {
to {
transform: translateX(-1000px);
}
}
<div class="container">
<div class="anim">
<div class="boxContainer">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
<div class="box">7</div>
<div class="box">8</div>
<div class="box">9</div>
<div class="box">10</div>
<div class="box">11</div>
<div class="box">12</div>
<div class="box">13</div>
<div class="box">14</div>
<div class="box">15</div>
<div class="box">16</div>
</div>
</div>
<button onclick="nextBox()">next box</button>
</div>
As you can see I create at animation that allow that click event nad he jump to next position but in some place animation restart in wrong place.
How to fix that issue in right and performance way ?
I am trying to achieve a "next page" slide animation in CSS and Javascript. If user clicks a div page, the current page move left and fade out and next page will replace the current container.
This is what I tried, but I don't know how to change container to have dimensions based on current page.
(function () {
document.querySelectorAll(".page").forEach((item, idx) => {
if (idx !== 0) {
item.classList.add("hidden");
item.style.maxHeight = 0;
} else {
}
});
document.querySelectorAll(".page").forEach((item) => {
item.addEventListener("click", (event) => {
const currentPage = event.target.closest(".page");
const nextPage = currentPage.nextElementSibling;
nextPage.style.maxHeight = "1000px";
nextPage.classList.add("show-page");
currentPage.classList.add("hide-page");
});
});
})();
.container {
font-family: inherit;
position: fixed;
bottom: 40px;
right: 40px;
background-color: #eb6383;
width: 300px;
padding: 10px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.page {
display: flex;
flex-direction: column;
transition: 1s;
left: 0%;
opacity: 1;
position: relative;
background-color: yellow;
}
.hidden {
position: relative;
overflow: hidden;
left: 100%;
transition: 1s;
}
.show-page {
position: relative;
left: 0%;
transition: 1s;
}
.hide-page {
opacity: 0;
left: -100%;
transition: 1s;
}
<div class="container">
<div class="page">
<div class="Header">page 1</div>
<div class="Content">
content page 1
</div>
</div>
<div class="page">
<div class="Header">page 2</div>
<div class="Content">
content page 2
</div>
</div>
<div class="page">
<div class="Header">page 3</div>
<div class="Content">
content page 3
</div>
</div>
</div>
Instead of moving each slide on it's own, we can animate a parent element holding all the slides
Here's a simplified version.
(function() {
let slides = document.querySelectorAll('.page');
let slidesCount = slides.length
let index = 0; // index
slides.forEach(slide => {
slide.onclick = (e) => {
/* Logic */
let nextIndex = (++index % slidesCount);
/* End Logic */
/* Management for the CSS */
// By how much we want to move, In Percents.
// A negative value because we're moving left
let ditance = -100;
// If nextIndex = 2, Then rawCssValue = -200
let styleValue = nextIndex * ditance;
/* Applying the CSS */
let style = `translateX(${styleValue}%)`;
e.target.parentElement.style.transform = style;
}
});
})()
.container {
font-family: inherit;
position: fixed;
bottom: 40px;
right: 40px;
width: 300px;
background: #eb6383;
overflow: hidden;
}
.page {
display: flex;
transition: 1s;
left: 0%;
opacity: 1;
position: relative;
background-color: yellow;
}
/* New */
.page {
flex: 0 0 auto;
height: 100%;
width: 100%;
}
.page + .page {
margin-left: 20px;
}
.slide {
padding: 10px;
box-sizing: border-box;
height: 100%;
display: flex;
flex-wrap: nowrap;
background: #eb6383;
transition: all .5s linear;
transform: translateX(0);
}
<div class="container">
<div class="slide">
<div class="page">
<div class="Header">page 1</div>
<div class="Content">
content page 1
</div>
</div>
<div class="page">
<div class="Header">page 2</div>
<div class="Content">
content page 2
</div>
</div>
<div class="page">
<div class="Header">page 3</div>
<div class="Content">
content page 3
</div>
</div>
<div class="page">
<div class="Header">page 4</div>
<div class="Content">
content page 4
</div>
</div>
</div>
</div>
I recommend using buttons for navigating through the slider, clicking the page to the move will become problematic very quick Because the children consume the event.
I'm trying to make the egg and basket game with JS, I just need to make a function that collects the eggs on it hits the basket, so any help to do it with a simple way:
<!--html code -->
<body class="home-page overflow-hidden ">
<div class="container-fluid">
<div class="heading-score-life d-flex justify-content-between">
<span class="ml-3 mt-1">Score 0</span>
<span class="mr-3 mt-1">Life 10</span>
</div>
<div class="container">
<div class="row">
<div class="col-4">
<div class="first hen d-flex justify-content-center">
<img src="photos/Happy-hen.svg" class="img-fluid henD">
</div>
</div>
<div class="col-4 ">
<div class="second hen d-flex justify-content-center">
<img src="photos/Happy-hen.svg" class="img-fluid henD">
</div>
</div>
<div class="col-4 ">
<div class="third hen d-flex justify-content-center">
<img src="photos/Happy-hen.svg" class="img-fluid henD">
</div>
</div>
</div>
<div class="row">
<div class="col-4">
<div class="first hen d-flex justify-content-center">
<img src="photos/Happy-Egg.svg" class="egg one">
</div>
</div>
<div class="col-4">
<div class="second hen d-flex justify-content-center">
<img src="photos/Happy-Egg.svg" class="egg two">
</div>
</div>
<div class="col-4 ">
<div class="third hen d-flex justify-content-center">
<img src="photos/Happy-Egg.svg" class="egg three">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div id="start-table" class="caption text-center m-auto">
<h1 class="pb-3 mt-4 text-white font-weight-bold">HAPPY EGGS</h1>
<button id="play" >PLAY</button>
</div>
</div>
</div>
<div class="basket-area">
<div class="row align-items-center">
<div class="basket" id="basket_move">
<img src="photos/Basket.svg" class="img-fluid">
</div>
</div>
</div>
<script src="js/jquery-3.4.1.min.js"></script>
<script src="js/popper.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
//css code
.home-page{
background-image: url(../photos/Background-Night.svg);
background-size: cover;
background-repeat: no-repeat;
background-position: center 43%;
height: 100vh;
}
.henD{
width: 40%;
animation:henscale 1s infinite linear;
}
#keyframes henscale {
0% {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05);
}
100% {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.home-page span {
font-family: "Roboto", sans-serif;
color: white;
font-weight: bold;
font-size: 1.5rem;
}
.caption {
height: 22vh;
background-color:#4C4660;
width: 60%;
border: 4px solid #FF4571;
border-radius: 70px;
margin-top: 50px !important;
}
.caption h1 {
font-size:300%;
}
.caption button{
border: 4px solid #fff;
background-color: #ff5f84;
border-radius: 100px;
color: #fff;
width: 200px;
height: 56px;
font-size: 42px;
text-align: center;
font-weight: 900;
letter-spacing: -3px;
line-height: 44px;
}
.basket{
width: 5rem;
}
.hes{
overflow: hidden
}
#basket_move{
position: absolute;
bottom: 50px
}
.dispalyNone {
display :none !important;
}
.dispaly{
display: flex !important;
}
.egg{
position: absolute;
z-index: 9999999999999999;
display: none;
}
.one{
width: 22px;
}
.two{
width: 22px;
}
.three{
width: 22px;
}
.first img {
position: relative;
z-index: 9999;
}
// JS code
var bascket = document.getElementById("basket_move");
var playBtn = document.getElementById("play");
var caption = document.querySelector(".caption");
var eggsO = document.querySelector(".one");
var eggsT = document.querySelector(".two");
var eggsTh = document.querySelector(".three");
var currentPosEgg = 0;
var requestAnimationFrame = window.requestAnimationFrame;
playBtn.onclick = function playBtn() {
start();
animation();
during()
}
function start() {
caption.classList.add("dispalyNone")
}
function during() {
eggsO.classList.add("dispaly")
eggsT.classList.add("dispaly")
eggsTh.classList.add("dispaly")
}
function animation() {
eggsO.style.top = currentPosEgg + "px";
currentPosEgg++
if (currentPosEgg >= 400) {
currentPosEgg = 0;
}
eggsT.style.top = currentPosEgg + "px";
currentPosEgg++
if (currentPosEgg >= 900) {
currentPosEgg = 0;
}
eggsTh.style.top = currentPosEgg + "px";
currentPosEgg++
if (currentPosEgg >= 800) {
currentPosEgg = 0;
}
requestAnimationFrame(animation);
}
document.addEventListener("mousemove", function (e) {
mouse(e);
})
function mouse(e) {
var x = e.clientX;
bascket.style.left = x + "px"
}
appreciate the soon reply to give me a simple way to do this function, and collect them in the score, native javascript: 0.0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
What you're looking for is collision detection - the way collision detection works is by checking if two shapes overlap. For the purposes of your game, representing the collision boundaries as rectangles at the same position, and with the same width and height as the width and height of the basket and egg textures in pixels should be sufficient.
First step is to create a rectangle structure, probably a class called Rectangle or something similar - for that you'd need to store the above mentioned values - the x and y positions on the screen, as well as the width and height as variables in the aforementioned Rectangle class.
Next, to check if two rectangles overlap, one could create a function that returns a Boolean as to whether the rectangles overlap or not. This can be easily determined using the following logical function:
...
function overlaps(rect) {
return x < rect.x + rect.width
&& x + width > rect.x
&& y < rect.y + rect.height
&& y + height > rect.y
}
...
Finally, to detect if the basket is overlapping any eggs, simply iterate over the rectangles for the eggs and check if they overlap the basket, if so - collect the egg.
As you might see I have fixed a kind of text box that will pop up when someone is hovering over that image, but honestly I want a slide-up effect that gone up slowly. Must be completely in pure JavaScript (no jQuery please!). Anyone knows how I can do that.
function show(myText) {
var elements = document.getElementsByClassName(myText)
for(var i = 0; i < elements.length; i++){
elements[i].style.visibility = "visible";
}
}
function hide(myText) {
var elements = document.getElementsByClassName(myText)
for(var i = 0; i < elements.length; i++){
elements[i].style.visibility = "hidden";
}
}
.text1 {
position: relative;
bottom: 28px;
text-align: center;
background-color: grey;
width: 100%;
height: 10%;
font-size: 20px;
color: white;
opacity: 0.7;
display: block;
visibility: hidden;
}
.text2 {
position: relative;
bottom: 28px;
text-align: center;
background-color: grey;
width: 100%;
height: 10%;
font-size: 20px;
color: white;
opacity: 0.7;
display: block;
visibility: hidden;
}
<div class="row">
<div class="col-md-6 col-sm-12">
<div class="tumb-wrapper">
<a href="http://www.bbc.com" target="_blank" class="image" onmouseover="show('text1')" onmouseout="hide('text1')">
<img src="https://i.vimeocdn.com/portrait/8070603_300x300" class="project" alt="print-screen"/>
<div class="text1">AAA</div>
</a>
</div>
</div>
<div class="col-md-6 col-sm-12">
<div class="tumb-wrapper">
<a href="http://www.cnn.com" target="_blank" class="image" onmouseover="show('text2')" onmouseout="hide('text2')">
<img src="https://lh6.ggpht.com/mSKQgjFfPzrjqrG_d33TQZsDecOoVRF-jPKaMDoGIpMLLT1Q09ABicrXdQH6AZpLERY=w300" class="project" alt="print-screen"/>
<div class="text2">BBB</div>
</a>
</div>
</div>
</div>
Here is a version of it that's totally javascript free, just using CSS. I'm going to edit this soon with a slight javascript addition (this current version requires you to have a fixed size).
.caption {
height: 250px;
width: 355px;
overflow: hidden;
}
.caption-image {
height: 100%;
}
.caption-text {
color: white;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
transition: transform 400ms ease;
}
.caption-image:hover + .caption-text,
.caption-text:hover {
transform: translateY(-100%);
}
<div class="caption">
<img class="caption-image" src="http://faron.eu/wp-content/uploads/2013/05/Cheese.jpg" />
<div class="caption-text">Some words about how cheesy it is to use a picture of cheese for this example!</div>
</div>
<div class="caption">
<img class="caption-image" src="https://top5ofanything.com/uploads/2015/05/Tomatoes.jpg" />
<div class="caption-text">There's nothing witty to say about a tomato, maybe some you say I say stuff. But honstly I can't think of anything...</div>
</div>
Version with JS sizing:
Basically the same idea, but when the page is loading it sets certain styles so the images can be what ever size you like.
var captionSel = document.querySelectorAll('.caption');
for (let i = 0; i < captionSel.length; i++) {
let image = captionSel[i].querySelector(":scope > .caption-image");
let text = captionSel[i].querySelector(":scope > .caption-text");
text.style.width = image.clientWidth - 20 + "px";
captionSel[i].style.height = image.clientHeight + "px";
}
.caption {
overflow: hidden;
}
.caption-text {
color: white;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
transition: transform 400ms ease;
}
.caption-image:hover + .caption-text,
.caption-text:hover {
transform: translateY(-100%);
}
<div class="caption">
<img class="caption-image" src="http://faron.eu/wp-content/uploads/2013/05/Cheese.jpg" />
<div class="caption-text">Some words about how cheesy it is to use a picture of cheese for this example!</div>
</div>
<div class="caption">
<img class="caption-image" src="https://top5ofanything.com/uploads/2015/05/Tomatoes.jpg" />
<div class="caption-text">There's nothing witty to say about a tomato, maybe some you say I say stuff. But honstly I can't think of anything...</div>
</div>
I'll give it to you even better: No javascript at all!
This is possible with pure CSS:
.tumb-wrapper {
position: relative;
overflow: hidden;
}
.text {
text-align: center;
background-color: grey;
width: 100%;
height: 10%;
font-size: 20px;
color: white;
opacity: 0.7;
display: block;
position: absolute;
bottom: -30px;
transition: 300ms;
left: 0;
}
.tumb-wrapper:hover .text {
bottom: 28px;
}
<div class="row">
<div class="col-md-6 col-sm-12">
<div class="tumb-wrapper">
<a href="http://www.bbc.com" target="_blank" class="image">
<img src="https://i.vimeocdn.com/portrait/8070603_300x300" class="project" alt="print-screen"/>
<div class="text">AAA</div>
</a>
</div>
</div>
<div class="col-md-6 col-sm-12">
<div class="tumb-wrapper">
<a href="http://www.cnn.com" target="_blank" class="image">
<img src="https://lh6.ggpht.com/mSKQgjFfPzrjqrG_d33TQZsDecOoVRF-jPKaMDoGIpMLLT1Q09ABicrXdQH6AZpLERY=w300" class="project" alt="print-screen"/>
<div class="text">BBB</div>
</a>
</div>
</div>
</div>
The transition css property animates whatever change you make. This way, when you hover over the .tumb-wrapper div, the .text div will slide up.
You should note however, that ancient IE versions won't be able to use this
I usually do this with only CSS.
Just save the first and second image right next to each other on one file... then you use css to change the position of the background image. To make things nicer i add a css-animation to the movement of the background image.
Example of my code:
<div id="thumb_Wrapper">
<div class="_Thumb">
<img src="images/Thumb.jpg" class="Animate_left">
</div>
</div>
The CSS
#_Container{position:absolute; bottom -60px; right:2px; width:626px; height:100px;}
._Thumb{position:relative; margin-right:4px; width:100px; height:80px; display:block; float:left; background:#EFEFEF; overflow:hidden;}
._Thumb > img{position:absolute; left:0; height:100%; background-size:cover; background-position:center;}
._Thumb > img:hover{left:-18px; cursor:pointer;}
CSS Animation
.Animate_left{transition:left .3s;}
Now all you have to do is swap out the image.
onHover - the image in the thumbnail will smoothly slide to the left; revealing the rest of the image/ showing the other image.
You can set how far to the left(or right) you want the thumb-image to first appear by adjusting the value of 'left' in the ._Thumb class.
You can set how far the image slides on hover by adjusting the img:hover{left:-18px} to what ever you like; instead of 18px.
I'm working on this code but I have difficulties implementing properly. I wan to place the arrow in front of the question and synchronize the click event with the text.
jsfiddle.net/tx8paL7L/5/
Can you help me to fix the issue?
HTML:
<div class="container faq_wrapper">
<div class="row">
<div class="span10 offset1">
<p>
</p>
<div class="faq-all-actions">
<a class="faq-expand">Expand All</a> | <a class="faq-collapse">Collapse All</a></div>
</div>
</div>
<div class="row">
<div class="span10 offset1">
<div class="question-wrapper">
<div class="arrows">
</div>
<div class="big-q">
Q</div>
<div class="question">
<div class="arrow"></div><h6>Can I try the software before I buy it?</h6></div>
<div class="answer-wrapper">
<div class="big-a">
A</div>
<div class="answer">
Yes! Simply download a free trial and you'll have instant access to all features for 30 days, absolutely free. We don't require your credit card details or any commitment.</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.answer-wrapper {
display: none;
}
.arrow {
margin: 1em;
}
.arrow::before {
position: absolute;
content: '';
width: 0;
height: 0;
border: .5em solid transparent;
border-left-color: gray;
transform-origin: 0 50%;
transition: transform .25s;
}
.arrow.down::before {
transform: rotate(90deg);
transition: transform .25s;
}
JavaScript:
$(document)
.on('click','.row',function(){
$(this).find('.answer-wrapper').slideToggle();
})
.on('click','.faq-expand',function(){
$('.answer-wrapper').slideDown();
})
.on('click','.faq-collapse',function(){
$('.answer-wrapper').slideUp();
})
var arr = document.querySelector('.arrow');
arr.addEventListener('click', function(event) {
event.target.classList.toggle('down');
});
;
Here is a working fiddle with your javascript, the css still needs a bit of work:
JSFiddle
Basically you were using the wrong selectors for your jQuery.
HTML:
<div class="container faq_wrapper">
<div class="row">
<div class="span10 offset1">
<p>
</p>
<div class="faq-all-actions">
<a class="faq-expand">Expand All</a> | <a class="faq-collapse">Collapse All</a></div>
</div>
</div>
<div class="row">
<div class="span10 offset1">
<div class="question-wrapper">
<div class="arrows">
</div>
<div class="big-q">
Q</div>
<div class="question">
<div class="arrow"></div><h6>Can I try the software before I buy it?</h6></div>
<div class="answer-wrapper">
<div class="big-a">
A</div>
<div class="answer">
Yes! Simply download a free trial and you'll have instant access to all features for 30 days, absolutely free. We don't require your credit card details or any commitment.</div>
</div>
</div>
</div>
</div>
</div>
jQuery:
$(document).ready(function() {
.on('click','.row .question-wrapper',function(){
$(this).find('.answer-wrapper').slideToggle();
$('.arrow').toggleClass('down');
})
.on('click','.faq-expand',function(){
$('.answer-wrapper').slideDown();
$('.arrow').addClass('down');
})
.on('click','.faq-collapse',function(){
$('.answer-wrapper').slideUp();
$('.arrow').removeClass('down');
})
});
you've added position:absolute but done nothing to position the arrow .
add the following styles :
.arrow {
position:relative; // you need to add position relative
margin: 1em;
padding-left:10px;
}
.arrow::before {
position: absolute;
left:100%; // define where you would like the arrow to be placed .
content: '';
width: 0;
height: 0;
border: .5em solid transparent;
border-left-color: gray;
transform-origin: 0 50%;
transition: transform .25s;
}
use position relative and left for perfectly positioning your arrow .
FIDDLE HERE
To put arrow in front of the question you can use right 0 like this:
.arrow::before {
position: absolute;
right: 0;
content: '';
width: 0;
height: 0;
border: .5em solid transparent;
border-left-color: gray;
transform-origin: 0 50%;
transition: transform .25s;
}
When you are layout an element on position absolute, you can "fix" the element relative to the parent if you want (top, bottom, right, left).
Add "left: 190px" to ".arrow::before"
.arrow::before {
position: absolute;
content: '';
width: 0;
height: 0;
border: .5em solid transparent;
border-left-color: gray;
transform-origin: 0 50%;
transition: transform .25s;
left: 190px;
}