I just want to skew the parent and skew it back on the child.
Example : HTML
<div class="parent"> <!-- skew(-10deg) -->
<div class="child">Hello</div> <!-- skew(10deg) (skew back) -->
</div>
Example : CSS
.parent {
transform: skew(-10deg);
}
.child {
transform: skew(10deg);
}
Text inside seems ok with Firefox, Safari. But not Chrome and Opera its a bit blurry
I have to use -webkit-backface-visibility: hidden; for reduce box pixelated in Chrome
Firefox :
Chrome :
Firefox vs Chrome :
or zoomed by Photoshop
Live example : http://jsfiddle.net/1tpj1kka/
Any idea ?
NOTE !!! : web-tiki's answer is an another way solution to prevent the problem. But if any answered a real solution to resolved this skew back problem (real fix), I will accept the answer.
The "blurry text" after 2d or 3d transforms with webkit browsers has been discused many times. But in your case, you can apply the transform only on a pseudo element so that your text isn't affected by the skew property.
It will also alow you to use only one tag in your markup :
#import url(https://fonts.googleapis.com/css?family=Oswald);
body{color:#fff;font-weight: bold;font-size:50px;font-family:'Oswald',sans-serif;}
.parent {
width: 300px;
overflow: hidden;
padding-left: 5%;
position:relative;
}
.parent::before {
content :'';
position:absolute;
top:0;left:0;
width:100%; height:100%;
background: rgba(90,190,230,0.9);
transform-origin:0 0;
transform:skew(-10deg);
z-index:-1;
}
<div class="parent">
Hello
</div>
Adding the 'translateZ(0)' before transformations like below forces the gpu to re-render the text and removes blurry-ness on Chrome.
This:
transform: translateZ(0) skew(-10deg);
Not This:
transform: skew(-10deg);
You can try the text-rendering: geometricPrecision CSS property. This will force your text to not be anti-aliased, thus making the blurriness less important.
inp.onchange = function(){
document.querySelector('.child').classList.toggle('geo');
}
#import url(https://fonts.googleapis.com/css?family=Oswald);body{color:#fff;font-weight:bold;font-size:50px;font-family:'Oswald',sans-serif;}
.geo{
text-rendering: geometricPrecision;
}
.parent {
transform: skew(-10deg);
-webkit-backface-visibility: hidden;
width:300px;padding-left:15%;margin-left:-15%;overflow:hidden;
}
.child {
transform: skew(10deg);
width:300px;background: rgba(90, 190, 230, 0.9);padding-left: 5%;padding-right: 15%;
}
<div class="parent"> <!-- skew(-10deg) -->
<div class="child geo">Hello</div> <!-- skew(10deg) (skew back) -->
</div>
<input type="checkbox" id="inp" checked="true"/> geometricPrecision
Related
First question here. Please bear if I missed out anything. I'll try to add more details as soon as mentioned.
In my angular project, I have regular login and register form components and want to implement the flip animation to transition between them.
On click, the parent div has a flip animation and it "flips" from one component "front" to another "back" and vice-versa. The problem is that since the "back" component goes through transform: rotateY(180deg); the component's form field and animations don't work properly.
Due to this, even simple hover animations did not work as expected.
How should I implement this transition for both components + animations to work as expected?
Thank you for your time!
I followed the flip animation method given here but it is probably works fine just for display data and has problems when we put in a component with animations to the "back" side.
Adding a gif for better understanding of the entire problem : Entire problem in working
It's difficult know what happens.
I imagine you have any kind of confict with the name of some class of there're a problem using position absolute in your cards. check the "z-index" of your class. (I feel that the "border" you see is the border or the input in "front" - try enclosed each "face" in a div with position relative-)
With this .css
.scene {
perspective: 600px;
max-width:400px;
margin:auto auto 1rem;
}
.card {
position: relative;
transition: transform 1s;
transform-style: preserve-3d;
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15);
background: white;
}
.card__face {
float:left;
width:100%;
margin-right: -100%;
backface-visibility: hidden;
}
.card__face div{
padding:1rem;
background: white;
display:flex;
flex-direction: column;
backface-visibility: hidden;
}
.card::after{
display:block;
content:'';
clear:both;
}
.card__face--back {
transform: rotateY( 180deg );
}
.card.is-flipped {
transform: rotateY(180deg);
}
And this .html
<div class="scene">
<div #card class="card" [class.is-flipped]="toogle">
<div class="card__face card__face--front">
<div>
<mat-form-field appearance="outline">
<mat-label>Input front</mat-label>
<input matInput />
</mat-form-field>
<button mat-raised-button color="primary" (click)="toogle=!toogle">
click
</button>
</div>
</div>
<div class="card__face card__face--back">
<div>
<mat-form-field appearance="outline">
<mat-label>Input back</mat-label>
<input matInput />
</mat-form-field>
<button mat-raised-button color="accent" (click)="toogle=!toogle">
click
</button>
</div>
</div>
</div>
</div>
In this stackblitz that use material-angular looks like work
NOTE: It's necessary add in styles.css
.scene .mat-mdc-raised-button .mdc-button__label{
z-index: 0;
}
Because the raised-button add to the span a z-index:0
I'm trying to trigger a rotate animation in an SVG on my website. It definetly work but the problem is when i'm moving my mouse when i'm on hover the element it cancels the animation.
So i include an object svg element:
<object type="image/svg+xml" data="branching4.svg" id="branching">
Your browser does not support SVG
</object>
which is a long SVG document but here is stylesheet attached to it:
#rectangle1, #rectangle2, #rectangle3{
perspective: 1500px;
}
#rectangle1.flip .card, #rectangle2.flip .card, #rectangle3.flip .card {
transform: rotateX(180deg);
}
#rectangle1 .card, #rectangle2 .card, #rectangle3 .card{
transform-style:preserve-3d;
transition:1s;
}
#rectangle1 .face, #rectangle2 .face, #rectangle3 .face{
backface-visibility: hidden;
}
#rectangle1 #front1{
transform: rotateX(0deg);
}
#rectangle1 #back1{
transform: rotateX( 180deg );
}
#rectangle2 #front2{
transform: rotateX(0deg);
}
#rectangle2 #back2{
transform: rotateX( 180deg );
}
#rectangle3 #front3{
transform: rotateX(0deg);
}
#rectangle3 #back3{
transform: rotateX( 180deg );
}
#rectangle1.flipped, #rectangle2.flipped, #rectangle3.flipped {
transform: rotateX( 180deg );
}
You can see the svg structure in the jsfiddle
And finally the script:
window.onload=function() {
var svgDoc = $("#branching")[0].contentDocument; // Get the document object for the SVG
$(".st4", svgDoc).css("font-family", "robotolight,Helvetica Neue,Helvetica,Arial,sans-serif");
$("#rectangle1", svgDoc).hover(function(){
$(this, svgDoc).toggleClass("flip");
});
$("#rectangle2", svgDoc).hover(function(){
$(this, svgDoc).toggleClass("flip");
});
$("#rectangle3", svgDoc).hover(function(){
$(this, svgDoc).toggleClass("flip");
});
};
I also tried with CSS, it's the same problem.
Here is a jsfiddle:
https://jsfiddle.net/7f7wjvvt/
1st question:
How can i have a fluid rotate transition when moving the mouse on the element ?
2nd question:
How can i have a Y rotation that stay on the spot and not translate to the left ? Try it in the fiddle
3rd question:
Why the jsfiddle display the svg well in firefox and not in chrome?
Also, perspective doesn't seem to work in chrome ... WHY ?
Any ideas ?
Unfortunately, I think many of the problems you're experiencing are simply the result of bad browser support for (3D) css transforms on svg elements.
Moving the cards <g> elements to their own <svg> inside an ordinary <div>, and applying the interactivity to the div element would make stuff a lot easier.
.card {
display: inline-block;
transform-origin: center;
perspective: 1000px;
background: grey;
}
.card-inner {
width: 100px;
height: 200px;
transition: transform .4s;
}
.card-inner:hover,
.card:hover > .card-inner {
transform: rotateY(180deg);
}
<div class="card">
<div class="card-inner" style="background: yellow">
Add svg card here
</div>
</div>
<div class="card">
<div class="card-inner" style="background: blue">
Add svg card here
</div>
</div>
<div class="card">
<div class="card-inner" style="background: green">
Add svg card here
</div>
</div>
How can i have a fluid rotate transition when moving the mouse on the element ?
Once the card rotates, it easily looses hover. The hover state will be applied to underlying element though. If you make sure this is the card's parent, you can use this css rule for styling:
.card-inner:hover,
.card:hover > .card-inner {
transform: rotateY(180deg);
}
How can i have a Y rotation that stay on the spot and not translate to the left ? Try it in the fiddle
You'll have to use transform-origin, like you tried. It just doesn't work for svg elements...
transform-origin: center;
Why the jsfiddle display the svg well in firefox and not in chrome? Also, perspective doesn't seem to work in chrome ... WHY ?
Like I said, it just isn't supported properly...
Re your first problem with the flip
It looks like the problem is that when the cards spin, they shrink. Then the mouse is no longer over the card and when the card moves around again it re-enters and the mouseenter event fires again. Then the whole process repeats (as long as the mouse is moving).
The solution is to prevent the event from firing again until the animation i complete.
There are several ways to fix this, but here is one solution:
// Flag to keep track of whether rectangle1 is flipping
var flipping1 = false;
$("#rectangle1").mouseenter(function() {
// Only toggle the animation if we aren't already doing so
if (!flipping1) {
// Add the class to start the flip
$(this).toggleClass("flip");
// Set flag to mark that we are flipping
flipping1 = true;
// Then in just over a second, turn the flag off again
setTimeout(function () {
flipping1 = false;
}, 1010);
}
});
Here's a fiddle showing this technique working on just rectangle1.
https://jsfiddle.net/7f7wjvvt/4/
I don't have a complete answer but for your first question I'd suggest replacing the .hover with a .mouseenter trigger, and for the second one just lose the perspective.
Also, I tried prefixing your css but to no avail, seems there's some compatibility issues between the browsers here.
I have an HTML element and I need to display a folder / file path within it that can sometimes be very long.
I also want to keep it on a single line (within a width constrained container) so I obviously need to add some ellipsis to it.
Another requirement is that I should always see the deepest folder nodes in that path (this is helpful when the path is long, because the latest nodes is what you're actually interested in).
The problem is, this is quite hard to achieve if I'm to use the direction: rtl; CSS property, because it will move other characters around, such as / or even paranthesis.
Take a look at this example: https://jsfiddle.net/r897duu9/1/ (as you can see, I didn't use the text-overflow: ellipsis property as this will, for some reason, override the direction: rtl property).
What I've tried so far and it works on modern browsers is adding the unicode-bidi: plaintext; CSS property, but according to the Mozilla Developer Network this is experimental and not well supported across not-so-modern cough IE browsers. The fiddle for this is here: https://jsfiddle.net/n05b3jgt/1/ .
Does anyone know a better way to achieve this, that would be well supported across a wide range of browsers?
I looked at the other solutions but I think this is simpler and more effective.
.title-wrapper {
max-width: 200px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
direction: rtl;
}
.title {
unicode-bidi: plaintext;
}
<div class="title-wrapper">
<span class="title">asdasd/qweqwe/xcvxcv/rtyrty/dfgdfgdfgdfgdfgd</span>
</div>
You may use direction on container then reset it on text.
.container {
width: 340px;
background:gray;
direction:rtl;
overflow:hidden;
text-align:left;
position:relative;
}
.container:before{
position: absolute;
content: '...';
background: white;
left: 0;
}
.text-with-path {
display:inline-block;
white-space:nowrap;
text-indent:1em;
direction:ltr;
<div class="container">
<div class="text-with-path">
/Root/someFolder/SomeAnotherFolder/AgainSomeotherFolder/MyPictures/MyDocs (recent)
</div>
</div>
<hr/>
<div class="container">
<div class="text-with-path">
/MyPictures/MyDocs (recent)
</div>
</div>
or just use float if your main issue is which way text overflows
.container {
width: 340px;
background:gray;
overflow:hidden;
position:relative;
}
.container:before{
position: absolute;
background:gray;
content: '...';
left: 0;
}
.text-with-path {
float:right;
margin-left:-999px;
}
<div class="container">
<div class="text-with-path">
/Root/someFolder/SomeAnotherFolder/AgainSomeotherFolder/MyPictures/MyDocs (recent)
</div>
</div>
I'm trying to create a slider of images (previous/next) so the images slide to the left when I click "previous" and to the right when I click "next" with 0.5s of slowness, so it takes some animation. And when I reach the last image and click "next", I want images to "run backwards" to the first one, the same when I'm in the first one and click "previous", so it "run forward" until the last one.
I want the same behaviour this JSFiddle shows. (but I don't need the timer to move images automatically and don't need the "triggers" buttons, just "previous" and "next").
The problem here is that my images don't have fixed size. I define a width in percentage and can't define a height because I have responsive design, the image resizes as I resize the browser window.
The jQuery to previous/next actions is pretty easy, but I just can't find a way to add this animation when I remove/add the "active" class to my images (so they become visible or not).
I have already tried putting all images side by side and showing only the first one (setting container width equals to image width), so when I click "next" I just "move" the container to the left so it begins to display the next image, but it doesn't work because once I can't define the height of the images, they will appear underneath each other, not side by side.
JSFiddle
HTML
<div class="images">
<img class="active" src="1.jpg">
<img src="2.jpg">
<img src="3.jpg">
</div>
<div class="previous">previous</div>
<div class="next">next</div>
CSS
img {
width: 100px;
display: none;
float: left;
}
img.active {
display: block;
}
jQuery
$('.next').on('click', function() {
var active = $('img.active');
var next = active.next('img');
if (next.length) {
active.removeClass('active');
next.addClass('active');
} else {
active.removeClass('active');
$('.images img:first').addClass('active');
}
});
Well the problem is the height for sliding.
First you need to have an element which is the "picture frame" which hold all the other images. That's important.
For better imagination a picture:
Now you have several technics to show and hide images. One could be to set the opacity. When using transition: opacity .15s ease-in-out; The one Picture is fading out and the next on is fading in.
For the slideshow effect is given to the position of the visible image to its width to the left and the image previously purely new to his wide to the right and then to 0. Thus, moves the current picture on the left the frame out and the new comes out right in.
And here is the difficulty if the height is not the same. If the current image 300px high and the new 400px, so the image frame here would adjust his height immediately once the new image start to be visible.
The content below would start to jump with each slide.
Is that so desired???
If yes, I can make you an example how it works.
You can actually do this in Pure CSS!
You use an ID and a label (with a for attribute=for the targeted id)
That's basically it. All you have left is to style it! (Forked from Joshua Hibbert's Pen)
body {
background: #f7f4e2;
}
/* Slides */
.slider input {
display: none;
}
/* Buttons */
.slider label {
display: none;
cursor: pointer;
position: absolute;
top: 6em;
left: 50%;
transform: translateX(-50%);
color: #fff;
background: #000;
padding: 1.36em .5em;
opacity: .6;
font-size: 19px;
font-family: fantasy;
font-weight: bold;
transition: .25s;
}
.slider label:hover {
opacity: 1;
}
.previous {
margin-left: -188px;
}
.next {
margin-left: 188px;
}
#slide1:checked ~ .buttons .slide1 {
display: block;
}
#slide2:checked ~ .buttons .slide2 {
display: block;
}
#slide3:checked ~ .buttons .slide3 {
display: block;
}
#slide4:checked ~ .buttons .slide4 {
display: block;
}
/* Images */
.slider {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 300px;
margin-top: -150px;
margin-left: -200px;
white-space: nowrap;
padding: 0;
float: left;
transition: .25s;
overflow: hidden;
box-shadow: 0 0 0 3.12px #e8e8e8,
0 0 0 12.64px #eaebe4,
0 0 0 27.12px #000,
0 24px 3.824em 5.12px #000;
}
.slide {
width: 500em;
transition: .25s;
}
.slider img {
float: left;
width: 400px;
height: 300px;
}
#slide1:checked ~ .slide {
margin: 0;
}
#slide2:checked ~ .slide {
margin: 0 0 0 -400px;
}
#slide3:checked ~ .slide {
margin: 0 0 0 -800px;
}
#slide4:checked ~ .slide {
margin: 0 0 0 -1200px;
}
<div class="slider">
<input type="radio" name="slide" id="slide1" checked="true" />
<input type="radio" name="slide" id="slide2" />
<input type="radio" name="slide" id="slide3" />
<input type="radio" name="slide" id="slide4" />
<div class="buttons">
<!-- Slide 1 -->
<label for="slide4" class="slide1 previous"><</label>
<label for="slide2" class="slide1 next">></label>
<!-- Slide 2 -->
<label for="slide1" class="slide2 previous"><</label>
<label for="slide3" class="slide2 next">></label>
<!-- Slide 3 -->
<label for="slide2" class="slide3 previous"><</label>
<label for="slide4" class="slide3 next">></label>
<!-- Slide 4 -->
<label for="slide3" class="slide4 previous"><</label>
<label for="slide1" class="slide4 next">></label>
</div>
<div class="slide">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/872485/coldchase.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/980517/icehut_sm.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/943660/hq_sm.jpg">
<img src="http://dribbble.s3.amazonaws.com/users/322/screenshots/599584/home.jpg">
</div>
</div>
Although this method is the most compatible (except for old versions of IE) and depending on how you animate it this method can be more time consuming than a JS method, but can also be faster, it just depends on how you want the animations to go, or you could use a css library that does this for you.
Here are some css image sliders I recommend.
10 Amazing Pure CSS3 Image Sliders
http://bashooka.com/coding/pure-css3-image-sliders/
Pure CSS Image Slider Without Javascript #Codeconvey is a good solution for what you're looking for, but lots of CSS
http://codeconvey.com/pure-css-image-slider/
The downside to these along with what you're working on is that you can't touch to slide on a phone or tablet which is more common now a days with photo galleries.
I recommend checking out Fotorama it's amazing! :)
Perhaps not the ideal situation but at least it will give you an idea. you can use the animation function of jQuery and I also changed your code a bit. See demo here
Within your HTML I would say this:
<div id="images">
<div class="images-wrapper">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/02/In-the-spotlight.jpg">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/02/Bath-time-with-ducky.jpg">
<img src="http://www.cutestpaw.com/wp-content/uploads/2016/03/FB_IMG_1452981788903.jpg">
<img src="http://www.pictures-of-cats.org/images/Pixiebob-cat-list-of-cat-breeds-pictures-of-cats.jpg" />
</div>
</div>
<div class="previous">
previous
</div>
<div class="next">
next
</div>
and within your jQuery code you can animate the width:
$('.images-wrapper img:gt(0)').hide();
$('.next').click(function() {
$('.images-wrapper img:first-child').animate({width:'toggle'},350).next().fadeIn().end().appendTo('.images-wrapper');
});
$('.previous').click(function() {
$('.images-wrapper img:first-child').animate({width:'toggle'},350);
$('.images-wrapper img:last-child').prependTo('.images-wrapper').fadeOut();
$('.images-wrapper img:first-child').fadeIn();
});
With this implementation the whole process of changing and adding the active class to the image is removed and replaced by animation functions
Simplest solution (I think) is to force the items to be of the same size, by placing them in a div. You can even have the div show the image without the use of an img tag, by using the background-image CSS feature (see http://www.w3schools.com/css/css3_backgrounds.asp for more details).
The item CSS could look like:
.item {
background-size: contain;
background-position: center;
}
and in each item in the HTML:
<div class='item' style='background-image: url(img1.jpg)' />
<div class='item' style='background-image: url(img2.jpg)' />
<div class='item' style='background-image: url(img3.jpg)' />
I finally got there.
HERE is the fiddle with the solution I developed.
The main problem in the implementation of this image slider was that images, althought were all the same size, have dynamic width (defined in % on CSS) and dynamic height (not defined on CSS).
The solution was basically put an "fake" image (with opacity: 0) inside my container so the container get the actual size of images I will use in the slider; put a div to "hold" the real images with position: absolute and give it a width calculted by number of images * 100%; and for last, give each image in my slider a width of x%, based on number of images.
In the jQuery, I "move" the "images holder div" always by %, never by static values, once the width of everything can change if I resize the window.
If you start to slide the images to the left and right and then resize the window, you will see that it continues to work perfectly.
I have implemented using css3 animations. However this will require manipulating animation values in css every time a slide gets added or removed.
#keyframes slideAnim {
0% {
transform: translateX(0)
}
12.5% {
transform: translateX(0%);
}
25% {
transform: translateX(-25%);
}
37.5% {
transform: translateX(-25%)
}
50% {
transform: translateX(-50%)
}
62.5% {
transform: translateX(-50%)
}
75% {
transform: translateX(00%);
}
89.5% {
transform: translateX(00%)
}
100% {
transform: translateX(00%)
}
}
Here the animation values are set such that there is a pause between slide transitions. I have added a parent frame to show only one slide at a time.
Please refer this fiddle.
i trying to make this item draggable and rotatable.
however if i set transform:rotate(0deg);
i can drag everywhere in the parent container.
but if i set it to 90deg. there are some area became undraggable and it extended out of the parent container as well.
<div id="container">
<div id="myitem"><p>my rotate/drag</p></div>
CSS:
#container{
width:500px;
height:500px;
background:red;
}
#myitem{
width:115px;
height 50px;
background:black;
transform-origin:top left;
transform: rotate("90deg);
-ms-transform-origin:top left;
-ms-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
-webkit-transform-origin:top left;
}
look for the example here
click here for sample of the problem
Have solucioned the problem!
If capture $(foo).offset().left when set css scale the value is not equals to real position if use transform-origin: top left;
To fix this replace
$(foo).offset().left by parseInt($(foo).css('left').replace('px',))
but need set
position after run: foo{ top: 0; left: 0; position: absolute; }
:)
The problem is who detect transform-origin and difference of positions when apply an scale(). Calculate by %?
I just running around your question, basically you want a draggable and rotatable with container...
I have done some changes to your fiddle and try to achieve this, http://jsfiddle.net/28WG3/19/
Some changes to the html too:-
<div id="container">
<div id="main"><div id="myitem"><p>my rotate/drag</p></div>
</div>
</div>
Hope this works for you...