I have written simple swiper on in my vue app but I have a problem with containers which are not inline. The second is under the first one.
The second problem is that slider element should be visible only in viewport of swiper but it is not (viewport is border is blue).
I want to achieve a pretty effect of fluent slide show.
You can see it in my example:
https://jsfiddle.net/eywraw8t/547878/
How can I fix it?
<template>
<div class="swiper">
<transition-group
tag="div"
class="slides-group"
:name="transitionName"
>
<div :key="currentIndex" class="slide">
<slot v-bind:element="current" />
</div>
</transition-group>
<div class="pagination">
<button #click="next">next</button>
</div>
</div>
</template>
<script>
export default {
props: {
data: {
type: Array,
default: []
}
},
data() {
return {
currentIndex: 0,
transitionName: 'slide-next'
}
},
computed: {
current() {
return this.data[this.currentIndex];
}
},
methods: {
next() {
this.currentIndex++;
}
}
}
</script>
<style lang="scss" scoped>
.swiper {
width: 100%;
position: relative;
}
.slide-next-enter-active,
.slide-next-leave-active {
transition: transform 0.5s ease-in-out;
}
.slide-next-enter {
transform: translate(100%);
}
.slide-next-leave-to {
transform: translate(-100%);
}
.slide-prev-enter-active,
.slide-prev-leave-active {
transition: transform 0.5s ease-in-out;
}
.slide-prev-enter {
transform: translate(-100%);
}
.slide-prev-leave-to {
transform: translate(100%);
}
</style>
Try the following CSS changes
1)
to .swiper, add:
overflow:hidden;
2)
to .slide, add:
display: inline-block;
Then, change your transition settings for aesthetics.
.swiper {
margin-left: 100px;
position: relative;
border: 1px solid blue;
overflow:hidden;
}
.slide {
border: 1px solid red;
width: 200px;
height: 200px;
display:inline-block;
}
Please note, using an inline display will cause it to break into multi-lines if the line width exceeds the containers width.
You may want to set absolute displays on them with fixed positions, and manipulate those positions to achieve the desired affect.
Related
I`m trying to create a page, splitted horizontally or vertically. I want a nice transition between pages, splitted differently.
My solution is a background element with transform:rotateZ(0 or 90deg) and flex container with two elements:
<template>
<div id="app">
<div id="split-page-bg" :class="['split-' + splitType]"></div>
<div id="split-page" :style="{ 'flex-direction': flexDirection }">
<div id="split-page-part-first">
<p>Content #1</p>
<button #click="switchSplitType">{{ buttonText }}</button>
</div>
<div id="split-page-part-second">
<p>Content #2</p>
</div>
</div>
</div>
</template>
<script>
export default {
computed: {
buttonText() {
return (
"Switch to " +
(this.splitType === "horizontal" ? "vertical" : "horizontal")
);
},
flexDirection() {
return this.splitType === "horizontal" ? "column" : "row";
}
},
data() {
return {
splitType: "horizontal"
};
},
methods: {
switchSplitType() {
this.splitType =
this.splitType === "horizontal" ? "vertical" : "horizontal";
}
}
};
</script>
<style>
#app {
font-family: sans-serif;
font-size: 3rem;
height: 100vh;
width: 100vw;
padding: 0;
margin: 0;
}
#split-page-bg {
--w: max(200vw, 200vh);
--offset-percentage-vertical: 50vh;
--offset-percentage-horizontal: 50vw;
top: calc(-0.5 * var(--w) + 100vh - var(--offset-percentage-vertical));
left: calc(-0.5 * var(--w) + 100vw - var(--offset-percentage-horizontal));
width: var(--w);
height: var(--w);
position: fixed;
z-index: -10;
transition: transform 0.3s ease;
background: linear-gradient(0deg, #ff7d00 50%, #15616d 0%);
}
.split-horizontal {
--offset-percentage-vertical: 50vh;
}
.split-vertical {
transform: rotateZ(90deg);
}
#split-page {
width: 100vw;
height: 100vh;
display: flex;
}
#split-page-part-first {
flex: 0 1 50%;
}
#split-page-part-second {
flex: 0 1 50%;
}
button {
font: inherit;
}
</style>
Codepen
But it`s hard to work with separate background element. Sometimes background does not match with containers, there is a 1-2 px difference in width/height.
Question is, is there a better way for implementing this? Can I somehow animate containers like this and work with them in developer-friendly way?
I have a row of elements, and they have a hover animation to make them scale up. Is it possible to make other images next to them change position on scale to prevent the overlap?
body {
background-color:#1a1a1a;
}
img{
max-width: 15%;
transition-duration: 0.5s;
transform-origin: center;
border-radius: 25px;
overflow: hidden;
margin: 50px;
}
img:hover{
cursor: pointer;
transform: scale(110%);
}
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
<img src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg">
and example of the effect I am looking for would be something that looks like this:
This will scale images up and down, dependent on classes. I've amended your css slightly for display purposes and add the JS code (left comments as clear as possible).
// define function to return all siblings of hovered element
function getAllSiblings(element, parent) {
const children = [...parent.children];
return children.filter((child) => child !== element);
}
// grab all img elements
const imgs = document.querySelectorAll('img');
imgs.forEach((i) => {
// define siblings using function above
const siblings = getAllSiblings(i, document.getElementById('parent'));
// *hover in*
i.addEventListener('mouseover', function () {
// add an active class when hovered (amended your css)
this.classList.add('active');
// add small class to all sibling elements
siblings.forEach((sibling) => {
sibling.classList.add('small');
});
});
// *hover out*
i.addEventListener('mouseleave', function () {
// remove active class and small classes so hovered element reverts to normal
this.classList.remove('active');
this.classList.contains('small') && this.classList.remove('small');
// remove class small on all siblings so that everything is reverted to initial display
siblings.forEach((sibling) => {
sibling.classList.remove('small');
});
});
});
body {
background-color: #1a1a1a;
/* added for display purposes */
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* added for getting parent element */
#parent {
margin: auto;
display: flex;
justify-content: center;
align-items: center;
gap: 2rem;
width: 100%;
}
img {
max-width: 15%;
transition-duration: 0.5s;
transform-origin: top;
transform-origin: left;
border-radius: 25px;
}
/* added for changing hover states */
img.active {
max-width: 17%;
cursor: pointer;
transform: scale(120%);
transform-origin: center;
}
img.small {
max-width: 17%;
transform: scale(80%);
transform-origin: center;
}
<div id="parent">
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
<img
src="https://www.tazzadesign.com/wp-content/uploads/sites/65/2013/11/dummy-image-square.jpg"
/>
</div>
Check this out (after hover, the shape is changing width & height):
const divs = document.querySelectorAll('div');
const reset = () => {
divs.forEach(div => div.classList.remove('active'))
}
divs.forEach(div => div.addEventListener('mouseover', () => {
reset();
div.classList.toggle('active');
}));
divs.forEach(div => div.addEventListener('mouseout', () => {
reset();
}))
section {
height: 150px;
width: 600px;
display: flex;
justify-content: space-between;
align-items: center;
border: 2px solid red;
}
div {
flex: 1;
height: 100px;
border: 2px solid black;
transition: flex .2s, transform .2s;
margin: 1em;
}
div.active {
transform: scaleY(1.5);
flex: 2;
}
<section>
<div></div>
<div></div>
<div></div>
<div></div>
</section>
I'm new to VueJS. I spent the last two hours trying to animate a slider, and finally I found a solution, but I don't understand why I need to set my image in position absolute to have the slide effect using the transform: translate property. Can someone explain me why?
Here's the working code:
SCSS:
#slider {
margin-top: 20px;
width: 450px;
height: 187.5px;
position: relative;
overflow: hidden;
.layover {
#extend %layover;
}
.wrapper-image-slider {
width: 450px;
height: 187.5px;
position: relative;
overflow: hidden;
.slide-image {
width: 100%;
position: absolute; /* important */
top: 0;
left: 0;
bottom: 0;
right:0;
}
.thumb-text {
position: absolute;
top: 0;
left: 0;
}
}
.left-slide-enter-active, .left-slide-leave-active {
transition: 1s;
}
.left-slide-enter {
transform: translate(100%, 0);
}
.left-slide-leave-to {
transform: translate(-100%, 0);
}
}
HTML:
<div id="slider">
<div class="layover"></div>
<transition-group name="left-slide" tag="div" class="wrapper-image-slider">
<div v-for="(post, index) in slider" :key="post.id" v-if="(activeImageSlider == index)">
<img class="slide-image" :src="post.img">
<div class="thumb-text">
<div class="label">
{{ slider[activeImageSlider].label }}
</div>
<h2>
{{ slider[activeImageSlider].title }}
</h2>
<div class="descr">
{{slider[activeImageSlider].descr }}
</div>
</div>
</div>
</transition-group>
</div>
I don't think you need to use a list transition for this. If you create a computed property that just returns the active slide then you can use a normal transition with the mode 'out-in'.
https://jsfiddle.net/9oj1h8r3/1/
new Vue({
el: "#app",
data: {
activeSlideIndex: 0,
slides: [
{ img: "https://picsum.photos/200/300?random=1" },
{ img: "https://picsum.photos/200/300?random=2" },
{ img: "https://picsum.photos/200/300?random=3" },
{ img: "https://picsum.photos/200/300?random=4" }
]
},
computed: {
activeSlide() {
return this.slides[this.activeSlideIndex]
}
}
})
It should be simple, but I can't find how.
In this exemple, when adding or removing a new item, i would like to the the #app height change smoothly, instead of instantanly.
In pure css
Thanks for help.
https://codesandbox.io/s/sparkling-frog-qfy64
<template>
<div id="app">
<button #click="addItem">Add</button>
<button #click="removeItem">Remove</button>
<div v-for="(item, i) in items" class="box" :key="i">BOX</div>
</div>
</template>
<script>
export default {
name: "App",
data: () => ({
items: [1, 1]
}),
methods: {
addItem() {
this.items.push(1);
},
removeItem() {
this.items.pop();
}
}
};
</script>
<style>
#app {
text-align: center;
color: white;
margin-top: 60px;
background: blue;
height: auto;
transition: all 1.5s ease;
}
.box {
padding: 15px;
}
</style>
You need a measurement unit for it to be animated. height: auto won't do it.
You will need to compute the items height in JS.
This question already has answers here:
White space around css3 scale
(12 answers)
Closed 7 years ago.
I have a little problem with scale transformation. I wish resize element, but when I do, my old size occupies the space, and the next element undergoes this old size. How to remove this constraints ?
HTML
<!-- White space with Scale -->
<div class="scale"></div>
<div class="scale"></div>
<!-- Whitout Scale -->
<div></div>
<div></div>
CSS
div:nth-of-type(even) { background: blue; }
div:nth-of-type(odd) { background: red; }
div {
width: 100px;
height: 100px;
}
.scale {
transform: scale(0.5);
transform-origin: top left;
}
JSFiddle: https://jsfiddle.net/c7d2s21y/
Thank you for your response.
var scaleTo = 0.5,
itemWidth = $('.scaleB').width(),
itemHeight = $('.scaleB').height()
;
function scaleThis(meausure) {
var output = meausure * scaleTo;
return output;
}
$('.scaleB').on({
'mouseover': function(event) {
$(this).css({
'width' : scaleThis(itemWidth) + 'px',
'height' : scaleThis(itemHeight) + 'px'
});
},
'mouseout': function(event) {
$(this).css({
'width' : itemWidth + 'px',
'height' : itemHeight + 'px'
});
}
});
.wrapper {
background-color: #cccccc;
}
.wrapper:after {
content: "normal";
}
.wrapperScale {
background-color: #dddddd;
}
.wrapperScale:after {
content: "wrapped";
}
.wrapper_jQuery:after {
content: "jQuery";
}
.wrapper div:nth-of-type(even),
.wrapperScale div:nth-of-type(even) {
background: blue;
}
.wrapper div:nth-of-type(odd),
.wrapperScale div:nth-of-type(odd) {
background: red;
}
.scale, .wrapperScale div, .scaleB {
width: 50px;
height: 50px;
}
.scale:hover, .wrapperScale:hover {
transform: scale(0.5);
transform-origin: top left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="wrapper">
<!-- White space with Scale -->
<div class="scale"></div>
<div class="scale"></div>
</div>
<!-- Whitout Scale -->
<div class="wrapper wrapperScale">
<div></div>
<div></div>
</div>
<!-- jQuery -->
<div class="wrapper wrapper_jQuery">
<div class="scaleB"></div>
<div class="scaleB"></div>
</div>
That's that CSS transformations actually do, it doesn't affect the surrounding elements, you can try to wrap the DIVs inside another element and apply the scaling to that element, but it will not affect other elements outside, just the contents, other than that, you will have to manipulate the actual sizes from your DIVs via java Script or a js library such as jQuery.
You try this code i hope work for you :
<style>
div:nth-of-type(even) { background: blue; }
div:nth-of-type(odd) { background: red; }
div {
width: 100px;
height: 100px;
}
.scale {
transform: scale(1);
transform-origin: top left;
}
</style>