I've encountered a very strange bug in Google Chrome!
if I use mix-blend-mode property on en element then if I apply transform: translateZ(50px); to an element below it, it doesn't work!
Please see this:
function threeD_hover(params) {
// Get the elements inside to be animated ...
var el = params.parent.find(params.element),
// defining the factor to be whether concave or covex style ...
factor = 1;
if (params.convex) {
factor = -1;
}
// Set the nessecory styles
TweenMax.set(el, {
transformPerspective: params.perspective,
rotationY: 0.01,
rotationX: 0.01,
"transform-style": "preserve-3d",
"backface-visibility": " hidden"
});
// Thee core function fo each of the elements inside ...
el.each(function(index, el) {
var $this = $(this);
function core_func(e) {
// Defining the degrees ..
var ax = params.xSensitivity * (($this.offset().left + ($this.outerWidth() / 2)) - e.pageX) / 200,
ay = params.ySensitivity * (($this.offset().top + ($this.outerHeight() / 2)) - e.pageY) / 200;
// Setting the max deg amount ...
if (ax > params.maxRotateDegreeX) {
ax = params.maxRotateDegreeX;
} else if (ax < -params.maxRotateDegreeX) {
ax = -params.maxRotateDegreeX;
}
if (ay > params.maxRotateDegreeY) {
ay = params.maxRotateDegreeY;
} else if (ay < -params.maxRotateDegreeY) {
ay = -params.maxRotateDegreeY;
}
var dx = (-factor) * ax,
dy = factor * ay;
// Animating ...
TweenMax.to($this, params.movementTime, {
rotationY: dx,
rotationX: dy,
ease: params.easing
});
}
if (!params.mouseSensitiveArea) {
params.mouseSensitiveArea = params.parent;
}
// mosuse move on canvas ..
params.mouseSensitiveArea.on("mousemove", core_func);
});
}
threeD_hover({
parent: $(".section"),
element: $(".card"),
// convex: true, // if not set it is false or concave
maxRotateDegreeX: 30,
maxRotateDegreeY: 30,
xSensitivity: 5, // Min: 1 | Max: 10
ySensitivity: 10, // Min: 1 | Max: 10
perspective: 1000,
// mouseSensitiveArea: $window, // if not set it's the parent element
easing: Power4.easeOut,
movementTime: 1
});
.parent {
background-image: url("http://www.intrawallpaper.com/static/images/background-wallpapers-26_HgdHzBm.jpg");
font-family: "Playfair Display", georgia, serif;
}
.mix-blend-overlay {
mix-blend-mode: overlay;
color: #fff;
text-align: center;
}
.section {
padding: 20px 0;
display: block;
}
.card {
pointer-events: none;
padding: 20px;
background: white;
border-radius: 5px;
width: 400px;
height: 150px;
margin: auto;
transform-style: preserve-3d;
backface-visibility: hidden;
display: flex;
box-shadow: 0 0 5px rgba(0, 0, 0, .1);
position: relative;
}
.card-content {
margin: auto;
text-align: center;
transform-style: preserve-3d;
}
h1 {
transform: translateZ(100px);
}
p {
transform: translateZ(50px);
display: block;
}
p.related {
transform: translateZ(80px);
font-style: italic;
}
a {
color: #69c6b8;
pointer-events: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="section">
<div class="card">
<div class="card-content">
<h1>Just hover around</h1>
<p><small>by Ershad</small></p>
<p class="related"><strong>This has been done using TweenMax </strong></p>
</div>
</div>
</div>
<h1 class="mix-blend-overlay">Ershad</h1>
<div class="section">
<div class="card">
<div class="card-content">
<h1>Just hover around</h1>
<p><small>by Ershad</small></p>
<p class="related"><strong>This has been done using TweenMax </strong></p>
</div>
</div>
</div>
</div>
The 2 Cards on that demo have exactly the same structure, style and js function yet the latter won't work properly because and element with mix-blend-property is before it, try to remove it and it works just fine!!
How can I solve this problem?!
Related
I have been learning how to create a memory game and thought I was following the instructions carefully but I have run into a snag. In my html, I have a div for the card and two child divs to style the front and back of the card.
<div class="container">
<div id="memory_board">
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
</div>
</div>
The number of cards for the memory game will vary.
When I run the code, they are stacked on top of each other meaning when you click on one card, the back flips over as expected but the front flips over underneath its original position. Here is my codepen. How can I adjust me code so that it looks like the card flips over properly?
=============== Edit ===================
Quick question, when I include a link to codepen, do I still have include all of the code?
The css for this game is:
* {
margin:0;
padding:0;
box-sizing:border-box;
}
div.container {
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
}
div#memory_board{
background:#CCC;
border:#999 1px solid;
display: inline-block;
padding: 10px;
perspective: 1000px;
}
.card {
width:100px;
height:133px;
display: inline-block;
margin:0px;
padding:10px;
transition: transform 1s;
transform-style: preserve-3d;
transform-origin: center right;
cursor: pointer;
position: relative;
}
.card.is-flipped {
transform: translateX(-100%) rotateY(-180deg);
}
.cardFace {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardFaceFront {
position: inherit;
background: whitesmoke;
color: black;
font-weight: bold;
font-size: 40px;
border:#000 1px solid;
text-align:center;
vertical-align: middle;
transform: rotateY(180deg);
}
.cardFaceBack {
background: url("https://images.cdn2.stockunlimited.net/preview1300/playing-cards-
background_1608080.jpg"); no-repeat;
background-size: cover;
position: relative;
border:#000 1px solid;
}
In addition, the javascript for this program is:
var memory_array = ['A','A','B','B'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
const memory_board = document.getElementById('memory_board');
let getRndInteger = (min, max) => Math.floor(Math.random() * (max - min) ) + min
// the following function randomly shuffles elements in an array using the Fisher-Yates (aka Knuth) shuffle
let shuffle = array => {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function initiateCard () {
let card = document.querySelectorAll('.card');
card.forEach( card => card.addEventListener ( 'click', () => {
card.classList.toggle('is-flipped');
}));
}
function newBoard() {
let memoryArray = shuffle (memory_array);
for (let i = 0; i <= memoryArray.length - 1; i++) {
document.getElementById("front" + i).innerText = memory_array[i];
}
}
$( document ).ready(function() {
newBoard ();
initiateCard ();
});
When the game starts, the memory_array shuffles propery and each element is distributed to the cards. However, when you turn a card,
I thought I had followed the instructions but I do not understand why, when turned, the front face is below where the back was. What adjustments do I have to make, after turning the card, so the front of the card in the same place as the back of the card, not below it.
an animation or a gif will be of help to as what you want to achieve, from your comment in your code I could see you are trying to replicate this, but the way you structure your code doesn't seem to be as this
https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
Okay, so a couple of things. I couldn't get your js to work. Getting this error "Uncaught TypeError: Cannot set properties of null (setting 'innerText')".
And with your CSS you need to position the front and back with position: absolute; otherwise, they affect each other. The back was pushing the front down the page.
And if you set transform-origin: center center; you don't need to do the additional transform: translateY(-100%);
var memory_array = ['A', 'A', 'B', 'B'];
var memory_values = [];
var memory_tile_ids = [];
var tiles_flipped = 0;
const memory_board = document.getElementById('memory_board');
let getRndInteger = (min, max) => Math.floor(Math.random() * (max - min)) + min
// the following function randomly shuffles elements in an array using the Fisher-Yates (aka Knuth) shuffle
let shuffle = array => {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function initiateCard() {
let card = document.querySelectorAll('.card');
card.forEach(card => card.addEventListener('click', () => {
card.classList.toggle('is-flipped');
}));
}
function newBoard() {
let memoryArray = shuffle(memory_array);
for (let i = 0; i <= memoryArray.length - 1; i++) {
document.getElementById("front" + i).innerText = memory_array[i];
}
}
$(document).ready(function () {
newBoard();
initiateCard();
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div.container {
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
}
div#memory_board {
background: #CCC;
border: #999 1px solid;
display: inline-block;
padding: 10px;
perspective: 1000px;
}
.card {
width: 100px;
height: 133px;
display: inline-block;
margin: 0px;
/* padding: 10px; */
transition: transform 1s;
transform-style: preserve-3d;
cursor: pointer;
position: relative;
transform-origin: center center;
}
.card.is-flipped {
transform: rotateY(180deg);
}
.cardFace {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.cardFaceFront {
position: absolute;
background: whitesmoke;
color: black;
font-weight: bold;
font-size: 40px;
border: #000 1px solid;
text-align: center;
vertical-align: middle;
transform: rotateY(180deg);
}
.cardFaceBack {
background: url("https://images.cdn2.stockunlimited.net/preview1300/playing-cards-background_1608080.jpg") no-repeat;
background-size: cover;
position: absolute;
border: #000 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="container">
<div id="memory_board">
<div class="card is-flipped">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
<div class="card">
<div id="back0" class="cardFace cardFaceBack"></div>
<div id="front0" class="cardFace cardFaceFront" class="card"></div>
</div>
</div>
</div>
I am new to working on css/html and I was trying to do parallax effect contained in some border radius but every time I try to do it using a background (url) it doesn't seem to do what I want it to, so I was wondering if it'd be possible to do it from the img tag?
You can solve your problem using JS. Check out the example below. It will work for you. Have a nice day.
$('.img-parallax').each(function() {
var $image = $(this);
var $imageParent = $(this).parent();
function parallaxImg () {
var speed = $image.data('speed');
var imageY = $imageParent.offset().top;
var winY = $(this).scrollTop();
var winH = $(this).height();
var parentH = $imageParent.innerHeight();
// The next pixel to show on screen
var winBottom = winY + winH;
// If block is shown on screen
if (winBottom > imageY && winY < imageY + parentH) {
// Number of pixels shown after block appear
var imgBottom = ((winBottom - imageY) * speed);
// Max number of pixels until block disappear
var imgTop = winH + parentH;
// Percentage between start showing until disappearing
var imgPercent = ((imgBottom / imgTop) * 100) + (50 - (speed * 50));
}
$image.css({ top: imgPercent + '%', transform: 'translate(-50%, -' + imgPercent + '%)' });
}
$(document).on({
scroll: function () {
parallaxImg();
}, ready: function () {
parallaxImg();
}
});
});
#import url(https://fonts.googleapis.com/css?family=Amatic+SC:400,700);
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
font-family: "Amatic SC", cursive;
}
.block {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
font-size: 16px;
}
.block h2 {
position: relative;
display: block;
text-align: center;
margin: 0;
top: 50%;
transform: translateY(-50%);
font-size: 10vw;
color: white;
font-weight: 400;
}
.img-parallax {
width: 100vmax;
z-index: -1;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 0);
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="block">
<img src="https://unsplash.it/1920/1920/?image=1003" data-speed="-1" class="img-parallax">
<h2>Parallax 1</h2>
</div>
<div class="block">
<img src="https://unsplash.it/1920/1920/?image=1002" data-speed="1" class="img-parallax">
<h2>Parallax 2</h2>
</div>
<div class="block">
<img src="https://unsplash.it/1920/1920/?image=1014" data-speed="1" class="img-parallax">
<h2>Parallax 3</h2>
</div>
Having a flex layout with top, left, middle and right.
Middle is divided into main and foot.
Within the main I want to have fixed elements, kind of like an MDI, as well as static elements.
If one scroll the fixed element should stay in same position of view. But, it should be contained within the main element if it is moved above or to the left of main. As in: not overlap the top, left, right etc.
THIS:
Colors and margins added to make a visual representation of the layout
NOT THIS:
Below is a simplified sample with a container within a container.
If one select the fixed positioning for the sub "window" it stay in place on scrolling, but it overlaps the parent if moved outside.
I can use absolute and reposition it on scroll by using JavaScript, but wondered if there was a pure CSS / layout way to get the same result.
function set_style_pos (e) {
moveable.style.position = e.target.value;
}
function halt (e) {
e.preventDefault();
e.stopPropagation();
}
const drag = {
el: null,
ex: 0,
ey: 0,
xs: 0,
ys: 0,
move: function (e) {
halt(e);
drag.el.style.marginLeft = (e.clientX - drag.sx + drag.ex) + 'px';
drag.el.style.marginTop = (e.clientY - drag.sy + drag.ey) + 'px';
},
end: function (e) {
halt(e);
window.removeEventListener('mouseup', drag.end);
window.removeEventListener('mousemove', drag.move);
},
start: function (e) {
let cs;
halt(e);
window.addEventListener('mouseup', drag.end);
window.addEventListener('mousemove', drag.move);
drag.el = e.target;
cs = getComputedStyle(drag.el);
drag.ex = parseInt(cs.getPropertyValue('margin-left')) || 0;
drag.ey = parseInt(cs.getPropertyValue('margin-top')) || 0;
drag.sx = e.clientX;
drag.sy = e.clientY;
},
check: function (e) {
let t = e.target;
if (t.dataset.moveable == "1")
drag.start(e);
}
};
document.addEventListener('mousedown', drag.check);
document.addEventListener('change', set_style_pos);
lines.textContent = "scroll me\n".repeat(100);
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
display: flex;
flex-direction: column;
color: #444;
font: 14px sans-serif;
}
label {
cursor: pointer;
}
.outer {
display: flex;
padding: 20px;
background: goldenrod;
flex-grow: 1;
overflow: hidden;
}
.inner {
position: relative;
overflow: scroll;
background: gray;
flex-grow: 1;
}
.box {
position: absolute;
width: 140px;
height: 150px;
background: silver;
box-shadow: 0 0 3px red;
cursor: move;
margin-left: 90px;
margin-top: -5px;
padding: 20px;
}
.box div {
font-weight: 700;
pointer-events: none;
text-align: center;
}
<div class="outer">
<div class="inner">
<div class="box" id="moveable" data-moveable="1">
<div>Move Me</div><br />
<label><input type="radio" name="p" value="absolute" checked />absolute</label><br />
<label><input type="radio" name="p" value="fixed" />fixed</label>
</div>
<pre id="lines"></pre>
</div>
</div>
Just use z-index.
Example:
function set_style_pos (e) {
moveable.style.position = e.target.value;
}
function halt (e) {
e.preventDefault();
e.stopPropagation();
}
const drag = {
el: null,
ex: 0,
ey: 0,
xs: 0,
ys: 0,
move: function (e) {
halt(e);
drag.el.style.marginLeft = (e.clientX - drag.sx + drag.ex) + 'px';
drag.el.style.marginTop = (e.clientY - drag.sy + drag.ey) + 'px';
},
end: function (e) {
halt(e);
window.removeEventListener('mouseup', drag.end);
window.removeEventListener('mousemove', drag.move);
},
start: function (e) {
let cs;
halt(e);
window.addEventListener('mouseup', drag.end);
window.addEventListener('mousemove', drag.move);
drag.el = e.target;
cs = getComputedStyle(drag.el);
drag.ex = parseInt(cs.getPropertyValue('margin-left')) || 0;
drag.ey = parseInt(cs.getPropertyValue('margin-top')) || 0;
drag.sx = e.clientX;
drag.sy = e.clientY;
},
check: function (e) {
let t = e.target;
if (t.dataset.moveable == "1")
drag.start(e);
}
};
document.addEventListener('mousedown', drag.check);
document.addEventListener('change', set_style_pos);
lines.textContent = "scroll me\n".repeat(100);
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
display: flex;
flex-direction: column;
color: #444;
font: 14px sans-serif;
}
label {
cursor: pointer;
}
.outer {
display: flex;
padding: 20px;
background: goldenrod;
/*flex-grow:1; Disable to control the height for presentaion*/
height:200px !important;
overflow:hidden; /*to hide scrollme lines*/
}
.inner {
position: relative;
overflow: scroll;
background: gray;
flex-grow: 1;
}
.box {
position: absolute;
width: 140px;
height: 150px;
background: silver;
box-shadow: 0 0 3px red;
cursor: move;
margin-left: 90px;
margin-top: -5px;
padding: 20px;
}
.box div {
font-weight: 700;
pointer-events: none;
text-align: center;
}
.prevent{
width:200px;
height:200px;
display:flex;
background-color:blue;
color:white;
justify-content:center;
align-items:center;
font-weight:bold;
/*--The solution--*/
z-index:1;
}
<div class="outer">
<div class="inner">
<div class="box" id="moveable" data-moveable="1">
<div>Move Me</div><br />
<label><input type="radio" name="p" value="absolute" checked />absolute</label><br />
<label><input type="radio" name="p" value="fixed" />fixed</label>
</div>
<pre id="lines"></pre>
</div>
</div>
<div class="prevent">
Prevent overlap
</div>
I hope this helps.
Use a sticky container and let children be absolute.
Had tested with z-index, all over, before posting but had not found any satisfactory solution that way.
I also tried various with position: sticky, and there is where I found the solution at last :)
One can wrap the sub windows in a sticky container which is positioned top left of the main container.
Pros:
Simple
Fairly clean HTML structure
The window stay below scroll-bars of container
Positioning relative to content wrapper
Cons:
If one want to make it non-fixed / non-sticy one have to move the element to parent and vice versa.
Absolute positioned children will not expand the container – thus not rearranging the DOM flow. (Which was the issue on earlier attempts using sticky).
Tested in FireFox, Chrome, Vivaldi, Opera Mini and Opera.
The core of it:
<div class="outer">
<div class="main">
<div class="wrap-sticky">
<div class="sub-window">
Fixed Window
</div>
</div>
Other "normal" content
</div>
</div>
And:
.outer {
overflow: hidden;
}
.main {
position: relative;
overflow: scroll;
}
.wrap-sticky {
position: sticky;
top: 0;
left: 0;
}
.sub-window {
position: absolute;
}
function get_pos (el) {
let cs = getComputedStyle(el);
return [
parseInt(cs.getPropertyValue('left')) || 0,
parseInt(cs.getPropertyValue('top')) || 0
];
}
function set_style_pos (e) {
let [x, y] = get_pos (moveable);
if (e.target.value == "sticky") {
wrap_sticky.appendChild(moveable);
moveable.style.left = (x - inner.scrollLeft) + 'px';
moveable.style.top = (y - inner.scrollTop) + 'px';
} else {
inner.appendChild(moveable);
moveable.style.left = (x + inner.scrollLeft) + 'px';
moveable.style.top = (y + inner.scrollTop) + 'px';
}
}
function halt (e) {
e.preventDefault();
e.stopPropagation();
}
const drag = {
el: null,
ex: 0,
ey: 0,
xs: 0,
ys: 0,
move: function (e) {
halt(e);
drag.el.style.left = (e.clientX - drag.sx + drag.ex) + 'px';
drag.el.style.top = (e.clientY - drag.sy + drag.ey) + 'px';
},
end: function (e) {
halt(e);
window.removeEventListener('mouseup', drag.end);
window.removeEventListener('mousemove', drag.move);
},
start: function (e) {
halt(e);
window.addEventListener('mouseup', drag.end);
window.addEventListener('mousemove', drag.move);
drag.el = e.target;
[drag.ex, drag.ey] = get_pos(drag.el);
drag.sx = e.clientX;
drag.sy = e.clientY;
},
check: function (e) {
let t = e.target;
if (t.dataset.moveable == "1")
drag.start(e);
}
};
document.addEventListener('mousedown', drag.check);
document.addEventListener('change', set_style_pos);
lines.textContent = "scroll me\n".repeat(100) + "horiz".repeat(100) + 'END';
* {
box-sizing: border-box;
}
body {
margin: 0;
height: 100vh;
display: flex;
flex-direction: column;
color: #444;
font: 14px sans-serif;
}
label {
cursor: pointer;
}
.outer {
display: flex;
padding: 20px;
background: goldenrod;
flex-grow: 1;
overflow: hidden;
}
.inner {
position: relative;
overflow: scroll;
background: gray;
flex-grow: 1;
}
.box {
position: absolute;
width: 160px;
height: 100px;
background: silver;
box-shadow: 0 0 3px red;
cursor: move;
padding: 20px;
top: 20px;
left: 20px;
}
.box div {
font-weight: 700;
pointer-events: none;
text-align: center;
}
.wrap-sticky {
position: sticky;
top: 0;
left: 0;
}
<div class="outer">
<div class="inner" id="inner">
<div class="wrap-sticky" id="wrap_sticky">
<div class="box" id="moveable" data-moveable="1">
<div>Drag & Move Me</div>
<label><input type="radio" name="p" value="sticky" checked />In sticky</label><br />
<label><input type="radio" name="p" value="absolute" />In main</label>
</div>
</div>
<pre id="lines"></pre>
</div>
</div>
So I am not using any CSS framework like bootstrap to get responsiveness out of the box which is why I am having trouble making responsive layout.
Please see jsbin
I essentially what to auto-resize colorful boxes based on browser window size eg that should shrink or grow automatically based on window size. Colorful boxes inside their parent should always be in horizontal row but should be able to adjust their width and height like this example.
I tried using flex-wrap: nowrap; but it didn't do the trick :(
Please note that colorful boxes are using position:absolute with parent's position being relative. I am also adding left css property to these boxes via JavaScript to change their position for the sake of sliding animation.
function Carousel(options) {
options = options || {};
// options vars
let speed = options.speed || 1; // animation speed in seconds
let width = options.width || 200;
let height = options.height || 100;
let space = options.space || 30;
// other vars
let container = document.querySelector('.carousel-container .carousel');
let slides = container.querySelectorAll('.carousel-item');
let curSlide = null;
let prevSlide = null;
let nextSlide = null;
if (areSlidesPresent()) {
setup();
}
// functions //
function setup() {
// we assume first slide to be current one as per UI requirements
//slides[0].classList.add("current");
curSlide = slides[0];
// we assume second slide to be next as per UI requirements
nextSlide = slides[1];
// we assume last slide to be prev as per UI requirements
prevSlide = slides[slides.length - 1];
// position elements horizontally
positionSlides();
}
function areSlidesPresent() {
return slides.length > 0;
}
this.getCurrentSlide = function() {
return curSlide;
}
this.getNextSlide = function() {
return nextSlide;
}
this.getPreviousSlide = function() {
return prevSlide;
}
this.setNextSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(nextSlide);
// middle ones
for (let i = 2; i < slides.length; i++) {
allSlides.push(slides[i]);
}
allSlides.push(curSlide);
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
this.setPreviousSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(prevSlide);
allSlides.push(curSlide);
// middle ones
for (let i = 1; i < slides.length - 1; i++) {
allSlides.push(slides[i]);
}
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
function positionSlides() {
curSlide.style.marginLeft = '0px';
for (let i = 0; i < slides.length; i++) {
slides[i].querySelector('.carousel-content').style.width = (width) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height) + 'px';
let elementWidth = getStyle(nextSlide, 'width');
if (i === 0) {
slides[i].style.zIndex = -10;
//slides[i].style.opacity = '1';
slides[i].querySelector('.carousel-content').style.width = (width + 50) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height + 50) + 'px';
} else {
slides[i].style.zIndex = 0;
//slides[i].style.opacity = '0.7';
}
if (i > 0) {
slides[i].style.marginLeft = (space * 2) + 'px';
elementWidth = parseInt(elementWidth, 10) + space;
}
slides[i].style.transition = speed + 's';
slides[i].style.left = (elementWidth * i) + 'px';
}
}
function getStyle(el, prop) {
return window.getComputedStyle(el, null).getPropertyValue(prop)
.replace('px', '')
.replace('em', '');
}
}
// utility
function log(text) {
console.log(text);
}
var options = {
speed: 1, // animation speed
width: 250, // slide width
height: 150, // slide height
space: 25 // space in px between slides
};
var carousel = new Carousel(options);
function selectCurrent() {
log(carousel.getCurrentSlide());
}
function selectNext() {
carousel.setNextSlide();
}
function selectPrev() {
carousel.setPreviousSlide();
}
.carousel-container {
width: auto;
height: auto;
margin: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.carousel {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.carousel .carousel-item {
position: absolute;
transition: transform .5s ease-in-out;
color: #fff;
margin-left: 10px;
-webkit-box-reflect: below 10px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(70%, transparent), to(rgba(255, 255, 255, 0.2)));
}
.carousel .carousel-item:first-child .carousel-content {
opacity: 1;
}
.carousel .carousel-item .carousel-title {
font-size: 24px;
text-align: center;
}
.carousel .carousel-item .carousel-content {
font-size: 18px;
font-weight: bold;
border: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
}
/* temp css below */
body {
background: #2C374A;
padding-top: 150px;
}
.navigation {
display: flex;
align-items: center;
justify-content: center;
margin-top: 150px;
}
.button {
color: #444;
padding: 10px;
width: 60px;
cursor: pointer;
background: #CCC;
text-align: center;
font-weight: bold;
border-radius: 5px;
border-top: 1px solid #FFF;
box-shadow: 0 5px 0 #999;
transition: box-shadow 0.1s, top 0.1s;
margin: 10px;
}
.button:hover,
.button:hover {
color: #000;
}
.button:active,
.button:active {
top: 104px;
box-shadow: 0 1px 0 #999;
}
<div class="carousel-container">
<div class="carousel">
<div class="carousel-item">
<div class="carousel-title">Make a Call</div>
<div class="carousel-content" style="background:#0E6DE8;border:10px solid #78B1FA">Slide One</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Message</div>
<div class="carousel-content" style="background:#D90080;border:10px solid #E357A9">Slide Two</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Picture</div>
<div class="carousel-content" style="background:#FEC601;border:10px solid #FFDD64">Slide Three</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Video</div>
<div class="carousel-content" style="background:#3DB365;border:10px solid #90E0AB">Slide Four</div>
</div>
</div>
</div>
<div class="navigation">
<div class="button" onclick="selectNext()">Next</div>
<div class="button" onclick="selectCurrent()">Select</div>
<div class="button" onclick="selectPrev()">Prev</div>
</div>
Problem here was:
Width was hard-coded in your JS, so if width is in px it can't be responsive.
By applying position:absolute to you carousel-item, it forced the children to get out of the box.
What I did:
Got rid of the static width and other functionalities related to width from your JS
Removed position:absolute from carousel-item
Let me know if this is what you are expecting.
function Carousel(options) {
options = options || {};
// options vars
let speed = options.speed || 1; // animation speed in seconds
// let width = options.width || 100;
let height = options.height || 100;
let space = options.space || 30;
// other vars
let container = document.querySelector('.carousel-container .carousel');
let slides = container.querySelectorAll('.carousel-item');
let curSlide = null;
let prevSlide = null;
let nextSlide = null;
if (areSlidesPresent()) {
setup();
}
// functions //
function setup() {
// we assume first slide to be current one as per UI requirements
//slides[0].classList.add("current");
curSlide = slides[0];
// we assume second slide to be next as per UI requirements
nextSlide = slides[1];
// we assume last slide to be prev as per UI requirements
prevSlide = slides[slides.length - 1];
// position elements horizontally
positionSlides();
}
function areSlidesPresent() {
return slides.length > 0;
}
this.getCurrentSlide = function() {
return curSlide;
}
this.getNextSlide = function() {
return nextSlide;
}
this.getPreviousSlide = function() {
return prevSlide;
}
this.setNextSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(nextSlide);
// middle ones
for (let i = 2; i < slides.length; i++) {
allSlides.push(slides[i]);
}
allSlides.push(curSlide);
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
this.setPreviousSlide = function() {
if (areSlidesPresent()) {
let allSlides = [];
// build new order of slides
allSlides.push(prevSlide);
allSlides.push(curSlide);
// middle ones
for (let i = 1; i < slides.length - 1; i++) {
allSlides.push(slides[i]);
}
// now add to DOM after cleaning previous slide order
for (let i = 0; i < allSlides.length; i++) {
container.appendChild(allSlides[i]);
}
slides = allSlides;
setup();
}
}
function positionSlides() {
curSlide.style.marginLeft = '0px';
for (let i = 0; i < slides.length; i++) {
// slides[i].querySelector('.carousel-content').style.width = (width) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height) + 'px';
let elementWidth = getStyle(nextSlide, 'width');
if (i === 0) {
slides[i].style.zIndex = -10;
//slides[i].style.opacity = '1';
// slides[i].querySelector('.carousel-content').style.width = (width + 50) + 'px';
slides[i].querySelector('.carousel-content').style.height = (height + 50) + 'px';
} else {
slides[i].style.zIndex = 0;
//slides[i].style.opacity = '0.7';
}
if (i > 0) {
slides[i].style.marginLeft = (space * 2) + 'px';
// elementWidth = parseInt(elementWidth, 10) + space;
}
slides[i].style.transition = speed + 's';
// slides[i].style.left = (elementWidth * i) + 'px';
}
}
function getStyle(el, prop) {
return window.getComputedStyle(el, null).getPropertyValue(prop)
.replace('px', '')
.replace('em', '');
}
}
// utility
function log(text) {
console.log(text);
}
var options = {
speed: 1, // animation speed
width: 250, // slide width
height: 150, // slide height
space: 25 // space in px between slides
};
var carousel = new Carousel(options);
function selectCurrent() {
log(carousel.getCurrentSlide());
}
function selectNext() {
carousel.setNextSlide();
}
function selectPrev() {
carousel.setPreviousSlide();
}
.carousel-container {
height: auto;
margin: 25px;
display: flex;
}
.carousel {
flex: 1;
height: 100%;
width: 100vh;
/* overflow:hidden; */
display: flex;
align-items: center;
justify-content: center;
}
.carousel .carousel-item {
transition: transform .5s ease-in-out;
color: #fff;
flex: 1;
margin-left: 10px;
-webkit-box-reflect: below 10px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(70%, transparent), to(rgba(255, 255, 255, 0.2)));
}
.carousel .carousel-item:first-child .carousel-content {
opacity: 1;
}
.carousel .carousel-item .carousel-title {
font-size: 24px;
text-align: center;
}
.carousel .carousel-item .carousel-content {
font-size: 18px;
font-weight: bold;
border: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
}
/* temp css below */
body {
background: #2C374A;
}
.navigation {
display: flex;
align-items: center;
justify-content: center;
}
.button {
color: #444;
padding: 10px;
width: 60px;
cursor: pointer;
background: #CCC;
text-align: center;
font-weight: bold;
border-radius: 5px;
border-top: 1px solid #FFF;
box-shadow: 0 5px 0 #999;
transition: box-shadow 0.1s, top 0.1s;
margin: 10px;
}
.button:hover,
.button:hover {
color: #000;
}
.button:active,
.button:active {
box-shadow: 0 1px 0 #999;
}
<div class="navigation">
<div class="button" onclick="selectNext()">Next</div>
<div class="button" onclick="selectCurrent()">Select</div>
<div class="button" onclick="selectPrev()">Prev</div>
</div>
<div class="carousel-container">
<div class="carousel">
<div class="carousel-item">
<div class="carousel-title">Make a Call</div>
<div class="carousel-content" style="background:#0E6DE8;border:10px solid #78B1FA">Slide One</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Message</div>
<div class="carousel-content" style="background:#D90080;border:10px solid #E357A9">Slide Two</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Picture</div>
<div class="carousel-content" style="background:#FEC601;border:10px solid #FFDD64">Slide Three</div>
</div>
<div class="carousel-item">
<div class="carousel-title">Send a Video</div>
<div class="carousel-content" style="background:#3DB365;border:10px solid #90E0AB">Slide Four</div>
</div>
</div>
</div>
On my page I want elements that will serve as horizontal "breaks" in the same way as hr elements, but I would like them to be shaped like a sine function.
Is that possible? If so, how?
Here's a fiddle for you to complete: http://jsfiddle.net/pdov7u85/
HTML:
<p>Here's some red text</p>
<!--some element with id someElement will go here-->
<p>Here's some blue text, which should be divided from the red text with a wavy line</p>
CSS:
p:nth-of-type(1)
{
color: red;
}
#someElement
{
}
p:nth-of-type(2)
{
color: blue;
}
Challenge accepted.
.sine {
text-align: center;
}
.sine_span {
display: inline-block;
margin:0;
padding:0;
height: 20px;
width: 40px;
border: 1px solid black;
}
.sine_span_first {
border-bottom: none;
border-radius: 20px 20px 0 0;
transform: translate(-20px, 0) scale(2,1);
}
.sine_span_second {
border-top: none;
border-radius: 0 0 20px 20px;
transform: translate(20px, 20px) scale(2,1);
}
.sine_span_first_2 {
transform: translate(0, 20px) scale(1,2);
}
.sine_span_second_2 {
transform: translate(0, 60px) scale(1,2);
}
Flat curve
<div class="sine">
<span class="sine_span sine_span_first"></span><span class="sine_span sine_span_second"></span>
</div>
<br />
Sharp curve
<div class="sine">
<span class="sine_span sine_span_first sine_span_first_2"></span><span class="sine_span sine_span_second sine_span_second_2"></span>
</div>
Btw, shouldn't you use some gif image for this?
You could draw that sine function in javascript:
var canvas = document.getElementById("canvas");
if (canvas == null || !canvas.getContext) {
return;
}
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "rgb(11,153,11)";
for (var i = 0; i <= 1000; i++) {
var x = i * 5;
var y = Math.sin(5 * x + 1);
ctx.lineTo(0.5 + x, 25 - y * 24);
}
ctx.stroke();
JSFiddle
Or you could just use an SVG image like Paulie_D suggested.
As #Paulie_D said don't over think it.
Be semantic and use a HR, give it a height and a background image.
hr{
border:none;
height:82px;
background:url('http://i60.tinypic.com/df8y75.png');
background-size:50%;
}
eg.
http://jsfiddle.net/pdov7u85/3/
note: background-size is not supported in older versions of IE but I only used it for convenience.