Building horizontal slider - divs floating vertically - html

I am trying to build simple horizontal image slider with overflow:hidden and floating divs. Hovewer, I am not able to float them horizontally - they always appear in vertical order. I tried many examples from the web, hovewer I still don't know where I am wrong.
HTML:
<div id="slidingWindow">
<div class="slidingSection clearfix">Something something</div>
<div class="slidingSection clearfix">Again something</div>
</div>
CSS:
#slidingWindow {
overflow:hidden;
width: 470px;
height: 500px;
background-color: red;
}
.slidingSection {
margin: 5px;
background-color: green;
width: 470px;
height: 400px;
float: left;
}
.clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
This JSFiddle contains simplest example of my problem:
http://jsfiddle.net/v4udd47t/

If your support is IE10+ and are not concerned with Opera Mini, then you can use display: flex. That way you don't need any extra markup or even floats and clearfix.
Along with using flex you will also have to set a min-width on the slides that is equal to the container minus any margins and padding. In regards to margins and padding, the container will also have to accommodate any that are applied to the slides (I noticed you have a 5px margin on them).
HTML:
<div id="slidingWindow">
<div class="slidingSection clearfix">Something something</div>
<div class="slidingSection clearfix">Again something</div>
</div>
CSS:
#slidingWindow {
overflow:hidden;
width: 480px; /* width of slide + left and right margins */
height: 500px;
background-color: red;
display: -ms-flex;
display: -webkit-flex;
display: flex;
}
.slidingSection {
margin: 5px;
background-color: green;
width: 470px;
min-width: 470px; /* required */
height: 400px;
}
Below is a fork of your fiddle with the size reduced and having an animation on hover to show it is working properly:
#slidingWindow {
overflow:hidden;
width: 260px;
height: 300px;
background-color: red;
display: -ms-flex;
display: -webkit-flex;
display: flex;
}
.slidingSection {
margin: 5px;
background-color: green;
width: 250px;
min-width: 250px;
height: 200px;
-webkit-transition: -webkit-transform 750ms;
transition: transform 750ms;
}
#slidingWindow:hover > .slidingSection {
-webkit-transform: -webkit-translate3d(-260px, 0, 0);
transform: translate3d(-260px, 0, 0);
-webkit-transition: -webkit-transform 750ms;
transition: transform 750ms;
}
<div id="slidingWindow">
<div class="slidingSection">Something something</div>
<div class="slidingSection">Again something</div>
</div>

That's because you need to Wrap the individual sliders in another div that has a width = number of slides*width. I updated your example here, and made the overflow: scroll so you can see the difference http://jsfiddle.net/v4udd47t/1/
<div id="slidingWindow">
<div class="slider-container">
<div class="slidingSection clearfix">Something something</div>
<div class="slidingSection clearfix">Again something</div>
</div>
</div>
.slider-container {
width: 1000px;
}
to set the width dynamically you can do this
var number_of_slides = $(".slidingSection").length;
$(".slider-container").css('width', number_of_slides * 470 + "px");

Related

How can I transition a flexbox sliding in from the left, to be centered on the page?

I currently have a flexbox with css properties that look something like this:
#root {
display: flex;
width: 85%;
border: 1px #F2F0F0 solid;
margin: 0 -100%;
position: relative;
top: 15%;
height: 600px;
overflow: hidden;
align-items: center;
transition-property: margin;
transition-duration: 1s;
}
This pushes my flexbox entirely out of the screen, to the left. I now want to slide it in to the right, however, I read that you cannot use transition with computed values, like margin: 0 auto which is the css I would like my flexbox to transition to, in order to center my flexbox responsively to the center of my screen.
How can I make this possible? I'm sure I'm missing something simple. My currently transition is just to a margin that isn't responsive, nor centered.
#root.slide-in {
margin: 0 2%;
}
Edit:
My flexbox is inside of a container like this:
<div class="container">
<!-- I want to center this flexbox -->
<div id="root" class="flexbox"></div>
</div>
Instead of animating margin, you should use the CSS property transform, which is was created to use for this kind of transitions. Then you can leave the CSS layout properties such as margin and position intact. Unlike margin, changing transform will never change the positioning of surrounding elements.
https://developer.mozilla.org/en-US/docs/Web/CSS/transform
.container {
background: #eee;
padding: 10px;
cursor: pointer;
display: flex;
flex-direction: column;
}
#root {
align-self: center;
width: 85%;
height: 60px;
background: #ccc;
transition: 1s transform;
padding: 10px;
}
.hidden {
transform: translateX(-100vw);
}
<div class=container onclick="document.querySelector('#root').classList.toggle('hidden')">
<div id=root> This is #root </div>
<p>click to hide or show #root</p>
</div>
See below. Hope this helps.
#root {
display: flex;
width: 85%;
border: 1px #F2F0F0 solid;
position: relative;
top: 15%;
left: -100%;
height: 600px;
overflow: hidden;
align-items: center;
animation: slideIn 1s forwards;
}
#keyframes slideIn {
100% { left: 0; }
}
<div id="root">
<img src="http://via.placeholder.com/350x250">
</div>
Try justify-content: center, this centers elements horizontally whereas the align-items centers the elements vertically.
In yout case, you can set the correct margin, since your width is 85%.
Note also that the fact that the element is flex doesn't have relevance, it would affect only the children of the element, but not the position of itself
#root {
width: 85%;
border: 1px black solid;
margin: 0 -100%;
height: 600px;
transition-property: margin;
transition-duration: 1s;
}
body:hover #root {
margin: 0 7.5%;
}
<div id="root"></div>

Make div in flexbox grow on hover

I'm trying to implement a view that displays three columns. When the user hovers over one of them it should grow at expense of the others.
I have a few requirements:
I want each column to have a background image and it should not move when the column is resized.
There should be a smooth transition when columns grows/shrinks
It should work in at least Safari, Firefox and Chrome
I would also like to have each column separated by diagonal line if possible. This is what the end result should look like:
I have basic functionality working, but I've run into several problems:
I've not managed to get the background image to be fixed on the parent div
Transitions does not work in Safari
In the real context, which is a website based on Bootstrap, the background image moves by a pixel or two seemingly by random on Safari and Chrome.
I've tried to achieve the diagonal lines using clip-path, but it does not work in Safari and very poorly in Chrome
When changing column from the second to the third the first column is resized a bit
In Chrome the rightmost pixel column flickers while growing/shrinking
Any hints appreciated!
Here's my current code:
.content {
display: flex;
border: 1px solid #f00;
background: #fbb;
padding: 10px;
height: 800px;
color: #fff;
}
.col {
flex-grow: 1;
flex-basis: 0;
transition: flex-grow .3s;
-webkit-transition: flex-grow .3s;
border: 1px solid #0f0;
padding: 10px;
}
.col:hover {
flex-grow: 5;
transition: flex-grow .3s;
-webkit-transition: flex-grow .3s;
}
.col1 {
background: url(https://images.pexels.com/photos/130184/pexels-photo-130184.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
background-attachment: fixed;
}
.col2 {
background: url(https://images.pexels.com/photos/354939/pexels-photo-354939.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
background-attachment: fixed;
}
.col3 {
background: url(https://images.pexels.com/photos/259915/pexels-photo-259915.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
background-attachment: fixed;
}
<div class="content">
<div class="col col1">
<h1>Foo!</h1>
</div>
<div class="col col2">
<h1>Bar!</h1>
</div>
<div class="col col3">
<h1>Brovinkel!</h1>
</div>
</div>
With transform: skew() one can tilt the items.
As that will create an unfilled upper left and lower right area, widen the left/right will cover that.
Finally we then revert that skew for text/image, where I used a pseudo for the image.
Stack snippet
.content {
display: flex;
height: 400px;
color: #fff;
overflow: hidden;
border: 5px solid #f00;
background: lime;
}
.col {
position: relative;
overflow: hidden;
flex-grow: 1;
flex-basis: 0;
transition: flex-grow .3s;
transform: skew(-20deg, 0);
background: yellow;
}
.col + .col {
border-left: 10px solid #0ff;
}
.col:first-child {
margin-left: -100px;
}
.col:last-child {
margin-right: -100px;
}
.col::before {
content: '';
position: absolute;
height: 100%;
width: calc(100% + 200px);
margin-left: -100px;
display: block;
background-attachment: fixed;
transform: skew(20deg, 0);
}
.col:hover {
flex-grow: 3;
transition: flex-grow .3s;
}
.col1::before {
background: url(https://images.pexels.com/photos/130184/pexels-photo-130184.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
}
.col2::before {
background: url(https://images.pexels.com/photos/354939/pexels-photo-354939.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
}
.col3::before {
background: url(https://images.pexels.com/photos/259915/pexels-photo-259915.jpeg?w=1260&h=750&auto=compress&cs=tinysrgb);
}
.col h1 {
margin: 0;
padding: 10px;
transform: skew(20deg, 0);
}
.col:first-child h1 {
margin-left: 40px;
}
<div class="content">
<div class="col col1">
<h1>Foo!</h1>
</div>
<div class="col col2">
<h1>Bar!</h1>
</div>
<div class="col col3">
<h1>Brovinkel!</h1>
</div>
</div>

A moving element to push adjacent element only if they collide

I have a container with 2 children.
One child has dynamic width and at it's maximum width can fill the container
The other child has fixed width and starts off being hidden as it's starting point is to the right of the overflow:hidden container
What I want is the fixed-width child to move to the left so that it exactly fits into the right of the container such that
a) If both children fit into the container - the other element should say put on the left and
b) If there is no room for both elements - the fixed-width element should push the other element to the left as much as it needs to in order to fit into the right of the container.
Here is what I tried:
Attempt #1
.container {
width: 200px;
height: 50px;
border: 1px solid green;
overflow: hidden;
white-space: noWrap;
}
span {
height: 50px;
display: inline-block;
}
.child1 {
background: aqua;
float: right;
width: 50px;
margin-right: -50px;
transition: margin .2s;
}
.container:hover .child1 {
margin-right: 0;
}
.child2 {
background: tomato;
//width: 100%;
}
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Dynamic Width</span>
</div>
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Here is a Dynamic Width box</span>
</div>
Condition a) Succeeds but condition b) Fails
Attempt #2
.container {
width: 200px;
height: 50px;
border: 1px solid green;
overflow: hidden;
white-space: noWrap;
}
span {
height: 50px;
display: inline-block;
}
.child2 {
background: aqua;
width: 50px;
margin: 0;
float: right;
margin-right: -50px;
transition: margin .2s;
}
.container:hover .child1 {
margin-left: -50px;
}
.container:hover .child2 {
margin: 0;
}
.child1 {
background: tomato;
transition: margin .2s;
}
<div class="container">
<span class="child1">Dynamic Width</span>
<span class="child2">Fixed</span>
</div>
<div class="container">
<span class="child1">Here is a Dynamic Width box</span>
<span class="child2">Fixed</span>
</div>
Condition a) Fails and condition b) Succeeds
Can both conditions be fulfilled with CSS alone?
PS: The markup which I provided in the demos may be modified. Also CSS3 including flexbox is also fine.
Here is a CSS only solution.
The trick is to use this basic rule:
Consider two or more inline elements rendered side by side.
If you increase the width of the first element, the second elements is pushed to the right.
The problem is that you need the elements to move to the left. I solved this by inverting the X direction to the child elements scaleX(-1) and re-inverting again the container.
To help you better understand this, you can comment out the transform: scaleX(-1); in the jsfiddle link below, and watch what happens.
The beauty of this is that you don't need to know the width of the .child2. You just need to push it to the left.
.container {
width: 200px;
height: 50px;
border: 1px solid green;
overflow: hidden;
white-space: nowrap;
text-align: right;
transform: scaleX(-1);
}
span {
height: 50px;
display: inline-block;
transform: scaleX(-1);
}
.child1 {
background: aqua;
width: 50px;
margin-left: -50px;
float: left;
transition: margin-left .2s;
text-align: left;
}
.child2 {
background: tomato;
}
.container:hover .child1 {
margin-left: 0;
}
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Dynamic Width</span>
</div>
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Here is a Dynamic Width box</span>
</div>
Also on jsfiddle
Solution 2
Another slightly simpler solution is to use direction: rtl; on the container. By reversing the direction of inline elements from right to left, we achieve the same effect without the need to use CSS3 transformations.
See http://jsfiddle.net/epfqjtft/12/
Since css can't do conditional statements (bar media queries), I don't think this is truly possible with css alone.
update
I have seen that it is in fact possible using CSS3 transforms (which works in modern browsers). but just in case some users might want older browser support which CSS3 transforms cant provide, i'll leave this here anyway.
Apart from that, I've used positioning instead of floats to 'clean up' the styling (and attempted the jquery):
$('.container').hover(function() {
var parentWidth = $(this).width();
var thisWidth = $(this).find(".child1").width() + 50; /*i.e. width of fixed box*/
if (parentWidth < thisWidth) { /*if it doesn't fit, move it!*/
$(this).find('.child1').addClass("moveLeft");
}
}, function() {
$(this).find(".child1").removeClass("moveLeft");
});
.container {
width: 200px;
height: 50px;
border: 1px solid green;
overflow: hidden;
white-space: noWrap;
position: relative;
}
span {
height: 50px;
display: inline-block;
}
.child2 {
background: aqua;
width: 50px;
margin: 0;
position: absolute;
top: 0;
right: -50px;
transition: all .2s;
}
.child1 {
background: tomato;
transition: all .2s;
position: absolute;
top: 0;
left: 0;
}
.container:hover .child2 {
right: 0;
}
.moveLeft:hover {
left: -50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<span class="child1">Dynamic Width</span>
<span class="child2">Fixed</span>
</div>
<div class="container">
<span class="child1">Here is a Dynamic Width box</span>
<span class="child2">Fixed</span>
</div>
As for your 'solution', you will have to test if the child + 50px is greater than the parent width, if so, move child1. If not, no action is needed.
Okay, I changed LinkinTED's code a little bit. Try this:
http://jsfiddle.net/epfqjtft/9/
Of course, I don't know if it's something you can work with. These types of problems should be solved with Jquery.
.container {
width: 200px;
height: 50px;
border: 1px solid green;
display: table;
table-layout: fixed;
transition: all 2s;
}
span {
height: 50px;
display: table-cell;
transition: all .2s;
}
.child1 {
background: tomato;
width: 100%;
}
.child2 {
background: aqua;
width: 0px;
overflow: hidden;
transition: all .2s;
}
.container:hover .child2 {
width: 50px;
}
<div class="container">
<div class="wrapper">
<span class="child1">Dynamic Width</span>
</div>
<span class="child2">Fixed</span>
</div>
<div class="container">
<div class="wrapper">
<span class="child1">Here is a Dynamic Width box</span>
</div>
<span class="child2">Fixed</span>
</div>
.container {
width: 250px;
height: 40px;
border: 1px solid read;
overflow: hidden;
white-space: nowrap;
text-align: right;
transform: scaleX(-1);
}
span {
height: 50px;
display: inline-block;
transform: scaleX(-1);
}
.child1 {
background: pink;
width: 50px;
margin-left: -50px;
float: left;
transition: margin-left .3s;
text-align: left;
}
.child2 {
background: #####;
}
.container:hover .child1 {
margin-left: 0;
}
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Dynamic Width</span>
</div>
<div class="container">
<span class="child1">Fixed</span>
<span class="child2">Here is Dynamic Width box</span>
</div>

How to transform (move whole child dives) div to max width with css?

I have tried with these code. This is HTML code.
<div id="body">
<div id="back_1"></div>
<div id="back_2"></div>
</div>
Now I need to transform back_1 and back_2 divs max width of body div. I use like this. transform:translate(100%), but it is not working. It doesn't transform max width of body div. How can I transform (move whole child dives) that divs ?
I have created 2 DIVs for better understanding.
HTML
<div id="body">
<p>DEMO 1 (Flexible width)</p>
<div id="back_1"></div>
<div id="back_2"></div>
</div>
<div id="body1">
<p>DEMO 2 (fixed width of parent DIV)</p>
<div id="back_11"></div>
<div id="back_21"></div>
</div>
CSS
body{ color: #fff; }
#body {
width: auto;
background: red;
height: auto;
padding: 10px;
}
#back_1, #back_2 {
background: yellow;
width: inherit;
height: 50px;
border: 5px solid #fff;
}
#body1 {
width: 300px;
background: green;
height: auto;
padding: 10px;
margin-top: 10px;
}
#back_11{ margin-bottom: 10px; }
#back_11, #back_21 {
background: grey;
width: inherit;
height: 50px;
}
DEMO: SEE IN ACTION
DEMO1: Added On Hover for #body DIV's first DIV.
As per the clarification from you, it seems that you are trying to move the child divs within the parent upto the edge of the parent.
You started right with the transform: translate(100%).
One problem is that you have to specify which axis you want it to transalte. x-axis in your case and hence it should be translateX.
The other problem is that the 100% in translate is different from the usual percent units in CSS. The CSS percent units are dependent on the parent unit i.e. x% of parent's width/height etc. Whereas, the translate(100%) means 100% of the very element which is being translated.
So, in your case you have to carefully determine the parent width (the .body div) which should be in multiples of child's width. e.g. if parent is 100%, and child is 50%, then translate(100%) will translate the child by another 50% and hence reach the edge of the parent.
This will be more clear by this demo:
Demo: http://jsfiddle.net/abhitalks/Ze9cu/1/
Relevant CSS:
#body {
width: 100%;
height: 200px;
}
#back_2 {
width: 25%;
}
#back_2:hover {
-webkit-transform: translateX(300%);
}
Here, the child is 25% of its parent. So translateX(100%) will move it along the x-axis by only 25%. Making it translateX(300%) will make it move 3 times its own width.
You can use this to get you started as an example:
<style>
#body
{
background: gray;
width: 400px;
}
#back_1, #back_2
{
background: red;
position: relative;
width: 200px;
-moz-transition: .5s;
-webkit-transition: .5s;
-ms-transition: .5s;
-o-transition: .5s;
cursor: pointer;
}
#back_1:hover, #back_2:hover
{
width: 100%;
}
</style>
<div id="body">
<div id="back_1">Back1</div>
<div id="back_2">Back2</div>
</div>
EDIT::: Using jQuery and jQueryUI
<style>
#body
{
position: relative;
width: 200px;
background: gray;
height: 100px;
max-width: 400px;
}
#back_1
{
position: absolute;
width: 100px;
background: red;
height: 10px;
left: 0px;
}
</style>
<script src="jquery.js"></script> <!-- Your jQuery reference -->
<script src="jqueryUI.js"></script> <!-- Your jQuery UI reference -->
<script>
$(document).ready(function() {
$("#body").mouseover(function() {
var maxWidth = $("#body").css("max-width");
$("#back_1").animate({ left: maxWidth });
});
$("#body").mouseleave(function() {
$("#back_1").animate({ left: 0 });
});
});
</script>
<div id="body">
<div id="back_1"></div>
<div id="back_2"></div>
</div>
Your view study this address
http://www.w3schools.com/cssref/css3_pr_transform.asp
example
<style>
#body{
border:1px solid red;
height:500px;
}
#body div{
background-color: blue;
width: 500px;
height: 40px;
/*General*/
transform:translate(200px, 0px);
/*Firefox*/
-moz-transform:translate(200px, 0px);
/*Microsoft Internet Explorer*/
-ms-transform:translate(200px, 0px);
/*Chrome, Safari*/
-webkit-transform:translate(200px, 0px);
/*Opera*/
-o-transform:translate(200px, 0px);
border:1px soldi red;
transition:all 0.5s linear;
float:left;
margin:5px;
padding:10px;
}
#body:hover div{
/*General*/
transform:translate(100px, 50px);
/*Firefox*/
-moz-transform:translate(100px, 50px);
/*Microsoft Internet Explorer*/
-ms-transform:translate(100px, 50px);
/*Chrome, Safari*/
-webkit-transform:translate(100px, 50px);
/*Opera*/
-o-transform:translate(100px, 50px);
transition:all 0.5s linear;
margin:80px;
padding:80px;
}
</style>
<body>
<div id="body" >
<div id="back1"></div>
<div id="back2"></div>
</div>
</body>

CSS3 -ms-max-content in IE11

We can set in CSS3 -moz-max-content (for Firefox) and -webkit-max-content (for Chrome, Safari) as width, but it seems -ms-max-content is not working in Internet Explorer (IE11).
Update: Here is a sample code:
.button {
background: #d1d1d1;
margin: 2px;
cursor: pointer;
width: -moz-max-content;
width: -webkit-max-content;
width: -o-max-content;
width: -ms-max-content;
}
<div>
<div class="button"> Short t. </div>
<div class="button"> Looooooong text </div>
<div class="button"> Medium text </div>
</div>
This works on IE11, Chrome and Firefox
instead of
width: -moz-max-content;
width: -webkit-max-content;
width: -o-max-content;
width: -ms-max-content;
I used
width: auto;
white-space: nowrap;
-max-content it is not supported by IE, according to CanIuse.
So I created a fallback for IE that might help you, by setting .button to display:inline-block:
.button {
background: #d1d1d1;
margin: 2px;
cursor: pointer;
width: -moz-max-content;
width: -webkit-max-content;
width: -o-max-content;
/* width: -ms-max-content;*/
}
/* fallback for IE*/
.button {
display: inline-block;
}
<div>
<div class="button">Short t.</div>
<div class="button">Looooooong text</div>
<div class="button">Medium text</div>
</div>
UPDATE: (Based on OP comment)
It's working, but I don't want to display the elements inline.
here is the final answer:
.button {
background: #d1d1d1;
margin: 2px;
cursor: pointer;
width: -moz-max-content;
width: -webkit-max-content;
width: -o-max-content
/* width: -ms-max-content;*/
}
/* fallback for IE*/
.width {
width:100%
}
.button {
display: inline-block;
}
<div>
<div class="width">
<div class="button">Short t.</div>
</div>
<div class="width">
<div class="button">Looooooong text</div>
</div>
<div class="width">
<div class="button">Medium text</div>
</div>
</div>
NEW UPDATE
Nowadays and for awhile there is a cleaner approach to this issue, by simply setting the parent as display: flex, and you even won't need the *-max-content value in width property
.button {
background: #d1d1d1;
margin: 2px;
cursor: pointer;
}
/* the fix */
section {
display: flex
}
<section>
<div class="button">Short t.</div>
<div class="button">Looooooong text</div>
<div class="button">Medium text</div>
</section>
For text elements I tried word-break: keep-all; and it worked for me.
Work for flex div.
I use to change the height of the parent.
.div-parent {
display:-webkit-inline-box;
display:-ms-inline-flexbox;
display:inline-flex;
position: fixed;
top: -70px;
bottom: 0;
right: 0;
left:20px;
height: 70px;
opacity: 0;
}
.div-children{
display:block;
padding-left:15px;
padding-right:15px;
padding-top:0px;
padding-bottom:0px;
width: 100%;
}
$("<div class='div-children'>Content...</>").appendTo(".div-parent");
var hd=70;
while($('.div-parent')[0].scrollHeight > $('.div-parent')[0].clientHeight){
hd=hd+1;
$('.div-parent').css("height",hd+"px");
}
$('.div-parent').css("top","0");
$('.div-parent').css("opacity","1");