Animate two elements from a vertical alignment to horizontal alignment - javascript

I have a page with a label directly above a textbox, and this is all centered vertically within the page. After the input is verified I would like to shrink the elements and slide them to the top of the page, while simultaneously "rotating" them to be next to one another, with the label on the left and the textbox on the right. So essentially I want to go from this in the middle of the screen and large:
Label
Textbox
to this at the top of the screen and back to a regular size:
Label: Textbox
I just can't seem to figure out the best way to handle it.
To be clear here, I'm wanting to animate this. To go from the top example to the bottom of the example in fluid motion.
Here is a fiddle of what I'm beginning with: http://jsfiddle.net/xpvt214o/280404/
Here is a fiddle of what I'm wanting to end with: http://jsfiddle.net/xpvt214o/280396/
The motion to get from fiddle 1 to fiddle 2 needs to be animated. That's what I'm struggling with.

Initial response
You can use vertical-align: middle and text-align: center to vertically and horizontally center your content. In the example: .parent1
To have both div next to each other on the same horizontal level use display: inline-block. In the example: .parent2
.parent1, .parent2 {
vertical-align: middle;
text-align: center;
}
.parent1 {
font-size: 30px;
}
.parent2 {
font-size: 20px;
}
.parent2 > div {
display: inline-block;
}
.parent2 > div:nth-child(2):before {
content: ': ';
}
<div class="parent1">
<div>Label</div>
<div>Textbox</div>
</div>
<br /><hr />
<div class="parent2">
<div>Label</div>
<div>Textbox</div>
</div>
With animation
Bonus if you wish to animate it:
You will need transition to set the animation type and duration. Then prepare two CSS classes:
a default one called .parent positionning the item in the center of the screen
.parent {
position: absolute;
left: 25%;
top: calc(50% - 47px);
width: 50%;
vertical-align: middle;
text-align: center;
font-size: 40px;
transition: all 0.5s ease;
}
another one that will be toggled and which overwriting the position of the element to the top of the screen.
.parentMod {
top: 0px;
}
I have added an event listener attached to the button so you can see the animation by toggling the state with a mouse click:
const changeLayout = () => {
document.querySelector('.parent').classList.toggle('parentMod');
};
.container {
height: 200px;
}
.parent {
position: absolute;
left: 25%;
top: calc(50% - 47px);
width: 50%;
vertical-align: middle;
text-align: center;
font-size: 40px;
transition: all 0.5s ease;
}
.parentMod>div {
font-size: 20px;
display: inline-block;
}
.parentMod {
top: 0px;
}
.parentMod>div:nth-child(2):before {
content: ': ';
}
<div class="parent">
<div>Label</div>
<div>Textbox</div>
</div>
<button onclick="changeLayout()">Switch Layout</button>

Note: I have seen the result you wanted to achieve: smoothly translate the two elements from inline to inline-block. I've found a way to do this. As it is a completely different approach from my initial solution, I have decided to post another answer.
Setup
You can achieve the desired result with plain CSS but there are a couple of things to take care of.
we will position the main container .parent with absolute
.parent {
position: absolute;
/* dimensions */
width: 35%
height: 20%;
/* centered horizontally */
margin: 0 auto;
left: 0;
right: 0;
/* centered vertically */
bottom: 0;
top: 45%;
}
to change the layout .parent will get the class .parentMod which will overwrite some of .parent's initial properties:
.parentMod {
top: 10px;
height: 12%;
}
both sub elements are too positioned with absolute their vertical position inside .parent have to be set (with percentages to ensure the layout is responsive):
.parent > div:nth-child(1) {
left: calc(50% - 125px);
}
.parent > div:nth-child(2) {
left: calc(50% - 10px);
}
then we can set their position when the layout has changed:
both sub elements will have the same vertical position:
.parentMod > div:nth-child(1),
.parentMod > div:nth-child(2) {
top: 0px;
left: 0px;
right: 0px;
width: 100%;
}
the second sub element will have a vertical offset (it will be positioned below the first sub element):
.parentMod > div:nth-child(2) {
top: 35px;
}
Demo
Overall the result will look like:
const changeLayout = () => {
document.querySelector('.parent').classList.toggle('parentMod');
};
.parent {
position: absolute;
margin: 0 auto;
bottom: 0;
right: 0;
top: 45%;
left: 0;
width: 35%;
height: 20%;
font-size: 40px;
transition: all 2s ease;
}
.parent > div {
text-align: center;
width: 130px;
margin: 0px;
position: absolute;
top: 10px;
transition: all 2s;
}
.parent > div:nth-child(1) {
left: calc(50% - 125px);
}
.parent > div:nth-child(2) {
left: calc(50% - 10px);
}
.parentMod {
top: 10px;
height: 12%;
}
.parentMod > div:nth-child(1),
.parentMod > div:nth-child(2) {
top: 0px;
left: 0px;
right: 0px;
width: 100%;
}
.parentMod > div:nth-child(2) {
top: 35px;
}
<div class="parent">
<div>Label</div>
<div>Textbox</div>
</div>
<button onclick="changeLayout()">Switch Layout</button>

You can try positioning them absolutely and using flex-box on the parent to center-align them.
It's not a very flexible solution, but it gets the job done!
HTML
<div class="container">
<span id="one">Label</span>
<span id="two">Textbox</span>
</div>
CSS
.container {
position: relative;
width: 200px;
height:200px;
display: flex;
flex-flow: column;
align-items: center;
}
#one, #two {
font-size: 1em;
display: block;
height:1em;
text-align: center;
margin: 0;
transition: all 500ms ease;
}
#one {
position: absolute;
}
#two {
position:absolute;
margin-top:1em;
}
.container:hover #one,
.container:hover #two {
font-size: .75em
}
.container:hover #one{
margin-left: -10px;
}
.container:hover #two{
margin-top: 0;
margin-left:30px
}

Related

How to animate a pop up on show and close using css?

I have a layout as follows,
container - to hold all the cards.
card - div for containing information.
In the above Image, the left one shows the initial rendering of the screen,
When user clicks on any inner card, the corresponding card should popout/zoomout,
and when user click backs on pop up card, it should disappear and the first sceen should display.
The popup animation should be like that, it should start from the position of the card, we have clicked.
The popup close animation after second click(When popup is open), the animation should look like that, the popup should get minimized to the card clicked in the first step.
I have tried following code, but it is really animating..
let isOpen = false;
$(".child").on("click", function() {
if (!isOpen) {
$(".child").removeClass("active");
$(this).addClass("active");
isOpen = true;
} else {
$(this).removeClass("active");
isOpen = false;
}
})
* {
box-sizing: border-box;
}
.parent {
margin: 40px auto;
width: 400px;
height: 600px;
border: 1px solid #3b3b3b;
border-radius: 20px;
padding: 20px 40px;
position: relative;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.child {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #000;
border-radius: 40px;
cursor: pointer;
transition: all 0.5s ease-in;
}
.child.active {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 10;
border: 1px solid red;
background: #000;
border-radius: 20px;
color: #fff;
}
#keyframes zoomIn {
0% {
transform: scale(1.1);
}
50% {
transform: scale(1.2);
}
100% {}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
</div>
Please help me to simulate the same.
Your animation is pretty much complete. The problem as I see it is that when the .active class is added to a child, the other children fill up the void in the grid. This makes the active child not enlarge from its original position.
I made my own solution using CSS but without animations - and vanilla JavaScript. In my code (just as in yours) the child gets lose from the grid, gets an absolute position and then fills up the entire parent container with width: 100%; and height: 100%; I also added CSS specifications to the other children to stay put when this is happening (see below).
It's a rather snappy effect because transition is not applied to width and height unless the child is absolute positioned before the active class is added. To achieve a more "zoomy" effect is a bit more tricky:
You can observe for DOM attribute (class) mutations with JavaScript (in other words, add a class with absolute positioning, and when that operation is completed, add another class with width: 100%; and height: 100%;).
Or you could use position: absolute on all the child elements from the start, but then you also need to specify width, height, top, left etc.
Some other solution I'm too tired or not skilled enough to think of.
Current Solution
// Turn all 4 .child selectors into an integer array ranging from 0-3
let cardArray = Array.from(document.querySelectorAll(".child"));
// Loop over each integer [0-3] and give them an index number
// Listen for clicks, and then toggle the "larger" class onto the item with the corresponding index number [0-3]
cardArray.forEach(function(everyItem, index) {
everyItem.addEventListener("click", function() {
cardArray[index].classList.toggle("larger");
});
});
* {
box-sizing: border-box;
}
.parent {
margin: 40px auto;
width: 400px;
height: 600px;
border: 1px solid #3b3b3b;
border-radius: 20px;
padding: 20px 40px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 20px;
transition: all 0.5s;
/* relative position required for enlarged items to stay within parent container */
position: relative;
}
.child {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #000;
border-radius: 40px;
cursor: pointer;
transition: all 0.2s;
/* z-index not neccessary, just a precaution */
z-index: 1;
}
/* top/bottom/left/right required for the CURRENTLY ACTIVE child to resize from the correct corner.
:nth-child() with grid-area specified required for NOT CURRENTLY active children to stay put in grid. */
.child:nth-child(1) {
grid-area: 1 / 1;
top: 0;
left: 0;
}
.child:nth-child(2) {
grid-area: 1 / 2;
top: 0;
right: 0;
}
.child:nth-child(3) {
grid-area: 2 / 1;
bottom: 0;
left: 0;
}
.child:nth-child(4) {
grid-area: 2 / 2;
bottom: 0;
right: 0;
}
/* .larger class added with the help
of JavaScript on click */
.child.larger {
/* Unhinge from the grid */
grid-area: unset;
/* Position absolute in order to resize it */
position: absolute;
/* Fill the WIDTH of the parent container */
width: 100%;
/* Fill the HEIGHT of the parent container */
height: 100%;
/* z-index not neccessary, just a precaution */
z-index: 2;
background: #000;
opacity: 0.5;
color: #fff;
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
</div>
You can try achieve this with by css variables calculation, position: absolute and a separate .active class for each element.
let isOpen = false;
$('.child').on('click', function() {
if (!isOpen) {
$('.child').removeClass('active');
$(this).addClass('active');
isOpen = true;
} else {
$(this).removeClass('active');
isOpen = false;
}
});
*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--parent-width: 400px;
--parent-height: 600px;
--gap: 20px;
}
.parent {
margin: 40px auto;
width: var(--parent-width);
height: var(--parent-height);
border: 1px solid #3b3b3b;
border-radius: 20px;
position: relative;
}
.child {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #000;
border-radius: 40px;
cursor: pointer;
transition: all 0.5s ease-in;
position: absolute;
height: calc((var(--parent-height) / 2) - (var(--gap) * 2));
width: calc((var(--parent-width) / 2) - (var(--gap) * 3));
}
/* Init size */
.child:nth-child(1) {
top: var(--gap); /* padding top 20px */
left: calc(var(--gap) * 2); /* padding left 40px */
}
.child:nth-child(2) {
top: var(--gap);
right: calc(var(--gap) * 2); /* padding right 40px */
}
.child:nth-child(3) {
bottom: var(--gap); /* padding bottom 20px */
left: calc(var(--gap) * 2); /* padding left 40px */
}
.child:nth-child(4) {
bottom: var(--gap);
right: calc(var(--gap) * 2);
}
/* Full size */
.child:nth-child(1).active {
top: 0;
left: 0;
}
.child:nth-child(2).active {
top: 0;
right: 0;
}
.child:nth-child(3).active {
bottom: 0;
left: 0;
}
.child:nth-child(4).active {
bottom: 0;
right: 0;
}
.child.active {
width: 100%;
height: 100%;
z-index: 10;
border: 1px solid red;
background: #000;
border-radius: 20px;
color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
</div>

Center element with animation / transition

I'm trying to create a full screen menu that does a bottom-to-top movement and I'm having trouble when it comes to vertically centering it.
Basically, it comes out of the screen and should end up right in the middle of it (centered).
However, since it is a fixed menu with an unknown height and I'm using animations, the options available aren't many:
I can't use the margin: auto technique because the auto value doesn't work with transitions;
I'm trying to avoid using flexbox;
translateY() seems to work fine but it creates a top-to-bottom movement instead of the desired bottom-to-top one (see my code)
anything else? (preferably that works with older browsers, but I can also manage with using translateY if there's a way to change the direction)
$('#small-nav-btn').click(function() {
$('#overlay').addClass('open');
$('#close-menu-cross').addClass('open');
$('#nav').addClass('open');
})
$('#cross').click(function() {
$('#overlay').removeClass('open');
$('#close-menu-cross').removeClass('open');
$('#nav').removeClass('open');
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Now-Regular", sans-serif;
font-size: 12px;
font-weight: bold;
}
ul {
list-style-type: none;
}
a {
color: black;
}
#overlay {
background: #fff;
opacity: 0;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 0;
transition: all 1s ease 0s;
z-index: 1555;
}
#overlay.open {
opacity: 1;
height: 100%;
}
#small-nav-bar {
display: block;
width: 80%;
margin: 0 auto;
text-align: center;
color: black;
}
#small-nav-btn {
cursor: pointer;
}
#nav {
background: orange;
position: fixed;
top: -100%; /*I need it to be bottom: -100% for the bottom-top movement*/
left: 50%;
transform: translate(-50%, -50%);
transition: all 0.8s linear 0.1s;
z-index: 1556;
}
#nav.open {
top: 50%; /*Again, I need this to be bottom: 50%*/
}
#close-menu-cross.open {
display: block;
position: fixed;
top: 15px;
right: 20px;
z-index: 1556;
cursor: pointer;
}
#close-menu-cross {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav id="nav-container">
<div id="small-nav-bar">
<div id="small-nav-btn">BUTTON</div>
</div>
<ul id="nav">
<li><span>HELLO</span>
</li>
<li><span>HELLO</span>
</li>
</ul>
<div id="close-menu-cross">
<div id="cross">X</div>
</div>
</nav>
jsfiddle
Thanks in advance! :)
You were quite close. With just a few adjustments in the CSS, you have a full working demo:
$('#small-nav-btn').click(function() {
$('#overlay').addClass('open');
$('#close-menu-cross').addClass('open');
$('#nav').addClass('open');
})
$('#cross').click(function() {
$('#overlay').removeClass('open');
$('#close-menu-cross').removeClass('open');
$('#nav').removeClass('open');
})
#nav {
background: orange;
position: fixed;
top: 100%; /* 1 */
left: 50%;
transform: translate(-50%, 0); /* 2 */
transition: all 0.8s linear 0.1s;
z-index: 1556;
}
#nav.open {
top: 50%;
transform: translate(-50%, -50%); /* 2 */
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: "Now-Regular", sans-serif;
font-size: 12px;
font-weight: bold;
}
ul {
list-style-type: none;
}
a {
color: black;
}
#overlay {
background: #fff;
opacity: 0;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 0;
transition: all 1s ease 0s;
z-index: 1555;
}
#overlay.open {
opacity: 1;
height: 100%;
}
#small-nav-bar {
display: block;
width: 80%;
margin: 0 auto;
text-align: center;
color: black;
}
#small-nav-btn {
cursor: pointer;
}
#close-menu-cross.open {
display: block;
position: fixed;
top: 15px;
right: 20px;
z-index: 1556;
cursor: pointer;
}
#close-menu-cross {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav id="nav-container">
<div id="small-nav-bar">
<div id="small-nav-btn">BUTTON</div></div>
<ul id="nav">
<li><span>HELLO</span></li>
<li><span>HELLO</span></li>
</ul>
<div id="close-menu-cross">
<div id="cross">X</div>
</div>
</nav>
Notes:
The CSS offset properties (top, bottom, left, right), when applied to absolutely-positioned elements (which includes position: fixed), shift the element x-distance from the respective edge.
You have top: -100% in your code. This puts the element 100% above the top edge.
You then have it shifting to top: 50%. This puts the element halfway inside the container.
Essentially, your animation moves the element a distance of 150%, from above the window to inside it. The movement is top to bottom.
But you want the movement to go from bottom to top.
So start the element all the way at the bottom and off-screen (top: 100%), and have it shift up to halfway inside the container (top: 50%).
The transform: translate() rule simply fine-tunes the centering.
If translateY(-50%) is applied to the primary state (like in your code), it will shift 50% of the nav onto the screen before the transition (demo).
That's why I applied translateY(-50%) only to the transitioned state.
For a complete explanation see my answer here: Element will not stay centered, especially when re-sizing screen
jsFiddle

Using fadeIn() and fadeOut() successfully

I have a grid of items, some of which are images, and some are text (all vertically-aligned, using different CSS techniques). Clicking these hides the content with fadeOut(), and shows different content with fadeIn().
My question is two-part:
How can I get the initially-hidden content to not match the CSS of the front during the transition? The text is mis-aligned until the transition has finished.
And secondly, how can I toggle this switch so that the process can be reversed?
My CSS:
.outer {
position: relative;
width: 144px;
height: 144px;
float: left;
border: solid 1px #dddddd;
margin: 10px;
}
.inner {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
}
.inner img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
max-height: 124px;
max-width: 124px;
padding: 10px;
}
.inner p {
font-weight: 700;
font-size: 1.2em;
position: relative;
top: 50%;
padding: 10px;
-webkit-transform: translateY(-50%);
-moz-transform: translateY(-50%);
transform: translateY(-50%);
}
.back {
display: none;
}
And my JavaScript/jQuery so far:
$(".outer").click(function() {
$(this).find(".front").fadeOut();
$(this).find(".back").fadeIn();
});
A JSFiddle of my predicament can be found here.
You should fade the element .back in after the element .front has been faded out.
You would do this by invoking .fadeIn() within the .fadeOut() callback:
Updated Example
$(".outer").click(function () {
var self = this;
$(this).find(".front").fadeOut(function () {
$(self).find(".back").fadeIn();
});
});

Positioning z-index does not work as expected

I cannot position info-pop-title on top of bar-header as you can see from my current code the text "TEST----" is visible but under the bar-header element.
http://jsfiddle.net/uvh4ymh9/
Could you point me out what am I doing wrong and how to fix it
PS: I cannot change structure for the HTML, only CSS solution
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
.bar-header, .bar-footer {
position: fixed;
left: 0px;
width: 1280px;
z-index: 1;
background-color: rgba(50,50,50,0.5);
text-align: center;
}
.bar-header {
top: 0px;
height: 60px; /* safearea top 25 + content 20 + space bottom 15*/
}
.bar-header h1 {
position: fixed;
top: 25px; /* safearea top 25 */
left: 25px; /* safearea left */
font-size: 20px; /* content */
}
.bar-footer {
top: 670px;
height: 50px; /* safearea bottom 20 + content 20 + space top 10 */
font-size: 20px; /* content */
}
.bar-footer > ul {
position: fixed;
top: 680px; /* footer top 670 + space top 10*/
left: 1150px;
}
.bar-footer > ul li {
float: left;
}
.bar-footer li:nth-child(1) span {
color: blue;
}
#scene-main {
position: fixed;
top: 0px;
left: 0px;
width: 1280px;
height: 720px;
/*background: #ffffff url("/auth/assets/tv-safearea-transparent.png") no-repeat left;*/
background-color: darkgrey;
}
#btn-up, #btn-down {
position: fixed;
left: 1230px;
width: 50px;
height: 50px;
background-color: yellow;
outline: 1px solid black;
z-index: 200;
}
#btn-up {
top: 0px;
}
#btn-down {
top: 50px;
}
#content {
position: fixed;
top: 0px; /* header */
}
.content-section:first-child {
margin-top: 60px; /* header height content does not go under header */
}
.content-section {
background-color: lightgray;
outline: 1px solid black;
width: 1280px;
}
/* Content sizes */
.content-snippet {
height: 360px; /* 1 slots */
width: 1280px;
background-color: lightblue;
outline: 1px solid green;
}
.content-snippet:nth-child(even) {
background-color: lightcoral;
}
.content-section h2 {
position: relative;
top: 30px; /**avoid to go under the header bar*/
}
.active {
background-color: violet !important;
}
.snippet-pop-info {
position: fixed;
top: 640px; /*430 = final position as visible / 670 = final position as not visible */
width: 1280px;
height: 240px;
background-color: darkblue;
opacity: 1;
color: white;
}
.snippet-pop-info ul {
position: absolute;
top: 0px;
left: 1155px;
width: 100px;
}
.snippet-pop-info ul li {
width: 100px;
}
.snippet-pop-info .rating {
position: absolute;
top: 65px;
left: 25px;
unicode-bidi: bidi-override;
direction: rtl;
}
.snippet-pop-info .rating > span {
display: inline-block;
position: relative;
width: 20px;
}
.snippet-pop-info .rating > span:hover:before,
.snippet-pop-info .rating > span:hover ~ span:before {
content: "\2605";
position: absolute;
}
#info-pop-title {
position: fixed;
top: 0px;
left: 250px;
z-index: 1;
font-size: 30px;
color: white;
font-weight: bold;
}
#info-pop-description {
position: absolute;
overflow: hidden; /* hide content that does not fit in the columns*/
top: 25px;
left: 300px; /* TEST */
height: 80px;
width: 800px;
font-size: 20px;
-webkit-column-count: 2;
-webkit-column-gap: 10px;
column-count: 2;
column-gap: 10px;
}
</style>
</head>
<body>
<div id="viewport">
<div id="scene-main" class="scene" style="">
<div class="bar-header"><h1>ChannelLive logo</h1></div>
<div id="page">
<div id="content">
<div id="snippet-cnt-0" class="content-snippet">
0
<div class="snippet-pop-info" style="top: 720px;">
<h1 id="info-pop-title" style="word-wrap: break-word;">TEST-----------------</h1>
<div class="rating"><span>☆</span><span>☆</span><span>☆</span><span>☆</span><span>☆</span></div>
<div id="info-pop-description" style="word-wrap: break-word;">null</div>
<ul>
<li class="focusable" data-href="movie-play">Play</li>
<li class="focusable" data-href="movie-details">Details</li>
</ul>
</div>
</div>
</div>
</body>
</html>
It's not clear what you're trying to accomplish, but I can make Chrome work like Firefox by getting rid of the
position: fixed;
style from #content. Whether that will work in the larger context of your layout, I don't know, but the problem is that the way z-index works is weird and complicated, and involves not just individual fixed elements but also any fixed parents they might have.
edit — oh also, set the z-index of .snippet-pop-info to 2. Here is an updated version of your fiddle.
Make your
.bar-header, .bar-footer{
z-index:0;
}
This will do the trick. Since your z-index for .bar-header and .info-pop-title are the same.
Add z-index in your content div
#content
{
position:fixed;
top:0;
z-index:1;
}
I'm afraid you can't make it work with the way your html is nested.
The element you want to pull on top to cover the rest is located in the main container while your second element is isolated in the header. If you want to bring your info-pop-title there you'll have to change the z-index of your #page element, which will cover everything.
The only thing I see you can achieve with this structure would be to position your diverse containers relatively and change the css of your info-pop-title with a negative margin, position absolutely this time.

jQuery div slide to left on hover a div/nextarrow

I am trying to implement something like this http://www.jamieoliver.com (slider -> arrow on hover)
I have done this much http://jsfiddle.net/PXLJG/5/ In the jsfiddle script? The arrow must be stand. The div.class=content 'Text next article' must be slide to left next to the arrow.
$('.holdingbox').hover(function () {
$('.rightbox').stop().animate({
width : '120px'
}, 400)
}, function () {
$('.rightbox').stop().animate({
width : '-0'
}, 400)
});
HTML:
<div class="holdingbox">
<a href="#">
<div class="margined">
<div class="rightbox">
<div class="content"><p>Következő cikk</p></div>
</div>
<div class="leftbox"> > </div>
</div>
</a>
</div>
CSS:
div {
display : inline-block;
}
.holdingbox {
position: relative;
top: 0;
margin-left: 100px;
}
.leftbox {
position: absolute;
display: inline-block;
height: 36px;
background-color: #ac193d;
color: #FFF;
font-weight: bold;
padding: 1px;
}
.holdingbox a {
text-decoration: none;
color: #FFF;
display: block;
}
.leftbox img {
margin: 0 auto;
margin-top: 10px;
}
.rightbox {
position: relative;
display: inline-block;
overflow: hidden;
width: 0;
height: 50px;
vertical-align: top;
margin-right: 0;
}
.rightbox a {
text-decoration: none;
color: #FFF;
}
.content {
width: 120px;
position: absolute;
background-color: #ac193d;
height: 38px;
text-align: center;
left: 0;
top: 0;
right: 0;
color: #FFF;
}
.content p {
margin-top: 8px;
}
just add position: absolute; right: 0; in .rightbox class.
.rightbox {
display: inline-block;
height: 50px;
margin-right: 0;
overflow: hidden;
position: absolute;
right: 0;
vertical-align: top;
width: 0;
}
Working here - http://jsfiddle.net/PXLJG/7/
I tried to fix up the code you've already got but it needed some major rehauling so I've just re-done it all.
JSFiddle: http://jsfiddle.net/t2z9Q/
CSS
.container {
width: 120px;
position: relative;
overflow: hidden;
color: white;
}
.container .content {
width: 100px;
overflow: hidden;
position: absolute;
left: 120px;
float:left;
z-index: 99;
background: #ac193d;
}
.container .arrow {
float: right;
width: 20px;
position: relative;
color: black;
z-index: 100;
background: #ac193d;
}
JS
$('.arrow').hover(function() {
$('.container .content').stop().animate({left: '0'}, 400)
}, function() {
$('.container .content').stop().animate({left: '120px'}, 400)
});
HTML
<div class="container">
<div class="content">Next Article</div>
<div class="arrow">></div>
</div>
This way you lose a lot of the jargon html & css that isn't really required but still get the same effect.
You are applying inline-block style on all divs. Please revert to normal display of block.
div{
display: block;
}
or just remove it as the default display is block
http://jsfiddle.net/PXLJG/8/
That should solve your core issue.
Now if you want to show the arrow to the left of the text div, remove absolute position on the arrow.
Now you will be having a whitespace between the inline-block elements, that is the arrow and the text. To remove it easily remove the whitespace between those two div in HTML
http://jsfiddle.net/PXLJG/18/
For something exactly like as in the website, you can try positioning both arrow and text using absolute positioning and anchoring them with their right property.
This way, as the width increases it will expand from right to left.
http://jsfiddle.net/PXLJG/20/

Categories