I found code for a nice CSS3 Spinner (from link here: https://ihatetomatoes.net/create-css3-spinning-preloader/) which I implemented into my pages. I want to transform it to be able to render with relative percent height and width.
Demo on CodePen:
http://codepen.io/anon/pen/jBWmZY
My question
How to transform the spinner to make it use percents width and height instead of fixed 100px.
The aim is to be able to make it scale to the (wrapper on my codepen) available height.
As you see on the demo, the div is small. The loader doesn't scale as its height and width are fixed.
I tried to simply transform as follow:
.loader-spinner {
position: relative;
}
.loader {
width: 50%;
height: 50%;
min-height: 35px;
min-width: 35px;
}
But the result not as intended. If the div is too small, I use wrapper to set a 35px minimum height but it doesn't work properly. The border radius seems not to follow and the size is quite mismatching. Demo here: http://codepen.io/anon/pen/jBWmKZ
I think I miss something about the wrapper or other similar thing.
The problem is that when you change the values to percent, then the width and height don't remain in sync.
The loader works because the height and width together form a square which is rounded off by the border-radius
Change your loader class to
.loader {
display: block;
position: relative;
left: 100%;
top: 100%;
width: 14%; // These values roughly keep your
height: 98%; // width and height in sync
border-radius: 50% !important;
border: 3px solid transparent;
border-top-color: #3498db;
-webkit-animation: spin 2s linear infinite; /* Chrome, Opera 15+, Safari 5+ */
animation: spin 2s linear infinite; /* Chrome, Firefox 16+, IE 10+, Opera */
&:before {
....
}
&:after {
....
}
This will work for a 1920x1080 resolution. You will have to define different values for each resolution using media queries.
Related
I can't find a way to transition only one kind of transform in CSS.
I have a bunch of images (arms, legs, head etc.), that upon loading need to have a "transform: translate" applied to them so that they are in the right place before I do anything else.
I then want to have, say an arm, do a transition on just transform: rotate(20deg) on hover. The problem is that when transitioning, it will repeat the initial translation along with that rotation, but I only want it to do the rotation on hover. How can I make it only transition that one rotation?
In the example code below you can see that I make sure that the triangle is initially touching the other shape, using transform: translate. Then I do a transform: rotate on hover. It works, but it ALSO does the translate again.
(I suppose if the images could be placed in their right location without needing a transform: translate, that could perhaps solve it, but I don't know how to do that either. And It would just be better if I could isolate the transition to only transform: rotate.)
/* INITIAL PLACING OF THE IMAGES IN THEIR RIGHT PLACES */
img#Arm {
position: relative;
transform: translate(220px, 100px);
}
img#Body {
position: relative;
transform: translate(150px, 180px);
}
/* END OF PLACING OF THE IMAGES IN THEIR RIGHT PLACES */
/* THESE ARE THE TRANSFORMATIONS ON HOVER */
img#Arm {
transform-origin: 200px 200px;
transition: 1s ease-in-out;
}
section:hover img#Arm {
transform: rotate(25deg);
}
/* END OF TRANSFORMATIONS ON HOVER */
/* THIS IS TO KEEP THE LOGO PARTS GROUPED TOGETHER DESPITE WINDOW CHANGING RESOLUTIONS */
section.wrapper {
margin: 0 auto;
/* this keeps the logo centered on the page */
min-width: 800px;
/* Minimum width of your wrapper element */
max-width: 800px;
min-height: 800px;
max-height: 800px;
}
<section class="wrapper">
<img id="Arm" src="https://i.stack.imgur.com/yCC87.png" />
<img id="Body" src="https://i.stack.imgur.com/mmzDM.png" />
</section>
As you're overwriting your non-hover transform value on hover with the rotate, your arm gets positioned to its original position (like when there wouldn't be any translate on it).
As you can set multiple values for the transform property, just also add the translate on hover to it. This will keep your arm on the right position and just rotates it.
/* INITIAL PLACING OF THE IMAGES IN THEIR RIGHT PLACES */
img#Arm {
position: relative;
transform: translate(220px, 100px);
}
img#Body {
position: relative;
transform: translate(150px, 180px);
}
/* END OF PLACING OF THE IMAGES IN THEIR RIGHT PLACES */
/* THESE ARE THE TRANSFORMATIONS ON HOVER */
img#Arm {
transform-origin: 200px 200px;
transition: 1s ease-in-out;
}
section:hover img#Arm {
transform: translate(220px, 100px) rotate(25deg);
}
/* END OF TRANSFORMATIONS ON HOVER */
/* THIS IS TO KEEP THE LOGO PARTS GROUPED TOGETHER DESPITE WINDOW CHANGING RESOLUTIONS */
section.wrapper {
margin: 0 auto;
/* this keeps the logo centered on the page */
min-width: 800px;
/* Minimum width of your wrapper element */
max-width: 800px;
min-height: 800px;
max-height: 800px;
}
<section class="wrapper">
<img id="Arm" src="https://i.stack.imgur.com/yCC87.png" />
<img id="Body" src="https://i.stack.imgur.com/mmzDM.png" />
</section>
This question already has answers here:
Chrome / Safari not filling 100% height of flex parent
(5 answers)
Why is percentage height not working on my div? [duplicate]
(2 answers)
Closed 5 years ago.
I have made a splitter which works perfectly in Chrome.
However, it does not work in Safari. But if we change the height in .handle-inner from 100% to 400px, we will observe that the splitter (from the top down to 400px) becomes draggable. That means it is height:100% which did not work in Safari.
Does anyone know how to amend the code to make the splitter work in both Chrome and Safari?
Edit 1:
I made a more complex example which has similar structure as my real program. In my real program, I do not fix the height as 500px, I use the whole screen, and don't want to exceed it. Here is the splitter which works perfectly in Chrome, but height:100% does not work in Safari.
Here is the version with height: 100vh. We could see the height is too much in both Chrome and Safari. However, we do NOT know how to set max-height.
Your flex container (.flex-box) has a defined height of 500px.
Your splitter (.handle-inner) has a defined height of 100%.
However, .handle, which exists between them, does not have a defined height. Safari sees this as a missing link, which it considers a violation of the spec, which essentially says:
The parent of an element with a percentage height must have a defined height and it must be with the height property. Otherwise, the element with a percentage height must default to height: auto (content height).
Therefore, you need to add height: 100% to .handle.
Also, in your body element, you not only have your .flex-box element, but you also have a nav element with height: 250px. Depending on how a browser handles the overflow (250px + 100%), this may cause your splitter element to disappear off-screen, which is happening in Safari.
To avoid that problem, make these adjustments to your code:
* { box-sizing: border-box; } /* include borders and padding in width
and height calculations */
.flex-box { height: calc(100% - 250px); } /* compensate for nav height */
revised demo
Also, being that body is a column-direction flex container, you can also use flex properties (such as flex: 1 on .flex-box) to consume remaining space. You may not even need percentage heights. See my answer here for details.
revised demo
Try changing your height in .handle-inner from 100% to 100vh. Set it up like this with a fall back:
.handle-inner {
width: 10px;
margin-left: -5px;
height: 100%;
height: 100vh;
}
Edit: Replace your CSS with this
.flex-box {
display: flex;
width: 100%;
height: 500px;
}
.flex-box .col {
border: 1px solid grey;
flex: 1;
}
.handle {
width: 1px;
text-align: center;
background: grey;
transition: all ease-in 0.1s;
}
.draggable {
background: grey;
}
.handle {
width: 0.0000001px;
transition: all ease-in 0.1s;
z-index: 999;
background: grey;
}
.handle-inner {
width: 10px;
margin-left: -5px;
height: 100%;
height: 100vh;
}
If you are experiencing overflow, like you stated. Try a height/max-height property.
I am not that familiar with CSS animations. My client want to achieve the following result when hovering the contact button:
so to be clear:
the square's move from left to right and vice versa
when the square moves, the line underneath it changes color
the top image it the start state, the middle is during the effect (50%) and the bottom image is the end stage.
Is this achievable with only CSS or do I need JS as well?
How would I approach this?
I created a quick and dirty JSFiddle here: https://jsfiddle.net/x0b397pb/
As you can see, it is possible with just CSS. In this example I used pseudo elements (::before and ::after) to create most of the elements.
You mentioned "Im not that familiar with CSS animations". For this I used transitions.
transition: left 1000ms, right 1000ms, box-shadow 1000ms;
Each comma separated element is a value that will transition between 2 points. This transition happens on a change of the div, this can be on a hover, but also when applying another div (Through JS).
To created the effect of the lines gradually shifting in color I used another element that slides on top of the original two lines. The new lines originally have 0 width, but on hover they gain 100% width. With a transition transition: width 1000ms; this happens gradually.
Try not to use my code as your final example, as it is somewhat ugly. But I hope it gets the point across.
Here is a small demonstration of css transition:
Consider this HTML:
<div class="container">
<div class="box"></div>
</div>
With this CSS:
.container {
position: relative;
width: 400px;
height: 400px;
border: solid 1px black;
}
.box {
position: absolute;
width: 40px;
height: 40px;
top: 10px;
left: 10px;
background-color: red;
transition: all 1s;
}
.container:hover {
border-color: blue;
.box {
top: 200px;
left: 200px;
width: 160px;
height: 160px;
background-color: blue;
}
}
Or, check it on JsFiddle: https://jsfiddle.net/ronency/75ozjq3s/
.box {
background: linear-gradient(80deg, #f3efef, #90009f, #01060d);
background-size: 600% 600%;
animation: AnimationName 29s ease infinite;
}
#keyframes AnimationName {
0%{background-position:0% 51%}
50%{background-position:100% 50%}
100%{background-position:0% 51%}
}
I am applying CSS3 blur filter on an image, but unexpectedly the blur effect goes out of the image original size (at least on Webkit browsers ).
I used overflow: hidden; but it's not working.
Here is my code:
HTML:
<div class='container'>
<img src='img.jpg' class='blur' />
</div>
CSS:
body{
padding:0px;
margin: 0px;
background: #1f1f1f;
}
.blur{
-webkit-filter: blur(15px);
-moz-filter: blur(15px);
-o-filter: blur(15px);
-ms-filter: blur(15px);
filter: blur(15px);
}
.container {
border:1px solid #fff;
margin:40px;
float:left;
overflow: hidden;
}
And here is a fiddle
Any ideas?
By giving the img a negative margin such as
img {
margin: -5px;
}
... will hide the spillage. You can play around with the margin.
FIDDLE
EDIT: Why This Occurs
Applying blur... you are blending your element by whatever amount of px, em etc. you declare e.g. 5px. To create this blur, the element will be expanded/feathured by that amount outside of its current size.
So applying a negative margin essentially "clips" the size and prevents anything outside of it to work. "Clipping" it is one approach, another would be by wrapping the element with a div and declaring a height and width and applying overflow: hidden. This will mask the overflow.
As I was experiencing the exact same bug on Safari 8 I thought I'd post my solution.
In the above example, you'd just need to add
-webkit-filter:blur(0px);
to the container.
The blur effect always go beyond the width.
In your case you can fix the issue using one of the following techniques -
Try setting a width of your .container and reduce 15px + 15px from both height and width of the img using CSS calc() function.
Or you can just add a padding of 15px to the img
DEMO of 2nd solution
I don't know much about "blur" yet, but I'm guessing it spreads / blurs out the edges 15px (in this case) in every direction. When you add padding: 15px; to your .container class it looks fine:
.container {
border:1px solid #fff;
margin:40px;
float:left;
overflow: hidden;
padding: 15px;
}
here is the fiddle
Put height and width attributes that are smaller than the image on the container. A size of 1px less than the image seems to work well.
CSS:
.container {
/* ... */
width:399px;
height: 223px;
}
JSFiddle
If your background around the clipping box .outer can be solid, you can cheat with a drop shadow. http://jsfiddle.net/ffghjkbj/
.overflow{
width: 200px;
height: 200px;
overflow: visible;
background-color: transparent;
position: relative;
z-index: 4;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
margin: 30px;
}
.overflow:after {
content: "";
position: absolute;
display: block;
box-shadow: 0 0 0 40px #fff;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
}
.inner{
width: 100%;
height: 100%;
background: green;
filter: blur(10px);
-webkit-filter: blur(0px);
transition: all 0.5s ease-in-out;
-webkit-transform: scale(1.2 , 1.2);
-webkit-transform-origin: 50% 50%;
z-index: -1;
position: absolute;
-webkit-backface-visibility: hidden;
margin: 0px;
padding: 10%;
box-sizing: border-box;
}
.overflow:hover .inner{
filter: blur(10px);
-webkit-filter: blur(10px);
}
If you background is not solid, you could maybe use a border-image, with the same image than the background, to fake the effect, which would be almost the same than using a png mask with a hole in the middle, instead of a background, and moving the pseudo-object with the mask to the front with z-index.
The blurry border you see is generated by the .inner element being CLIPPED (by its parent) BEFORE the blur is applied. Definitely a way for the acceleration not to waste power in rendering hidden areas.
So the .inner element is ALREADY clipped at the parent's edges when the blur is applied to it, and the blurry frame is actualy the outside empty area bleeding inside the image when blurred. The blur is NOT applied to the whole inner element as we would imagine if the element was "inside" or "behind". Just to the visible part. (This is why an oversized .inner element as suggested above won't work).
It's not obvious because the idea of a children element "inside" or "behind" its parent is in our mind. Objects just happen to be clipped at the paren't coordinates, but are actually IN FRONT of the parent.
Short version: Make the image fit nicely the visible area for small windows, starting from this fiddle
Update: There doesn't seem to be a solution for this issue. I thought there might be one because Chrome actually makes it possible (see my answer) but behavior is different in other browsers.
Longer version:
I'm working on a lightweight fluid lightbox and have an apparently simple CSS issue I can't resolve.
I want the content (a single image) to be downsized if needed to fit, while keeping the aspect ratio the same.
Here's a demo fiddle: http://jsfiddle.net/3a9y9/2/ . Resize the window so the image doesn't fit height wise.
It almost works, but the height given to the image is slightly more than what's actually visible so a bit of the bottom gets clipped. I've tried tweaking things to no avail; I wish I understood how come the available height is too high.
Maybe it's related, but IE 9 doesn't even maintain the aspect ratio with this attempt of a solution. Also, Chrome behaves strangely when resizing the window and clicking on run in the fiddle will sometimes redraw differently.
What's the solution?
It's no problem to wrap the <img> in a <div> or two if it's necessary, but the top-level structure should ideally remain the same (i.e. a .featherlight-content inside a .featherlight and that's it).
In featherlight.min.css, change .featherlight-image{width: 100%} to .featherlight-image{max-width: 100%}
and at the end, write the following css:
#media only screen and (min-height:1000px) {
.featherlight-image { height: 900px; }
}
#media only screen and (min-height:700px) {
.featherlight-image { height: 600px; }
}
#media only screen and (max-height:700px) {
.featherlight-image { height: 400px; }
}
What it's doing is changing the width of the lightbox from fixed 100% into a maximum of 100% (so that it's adjusted as per height). And then with #media, the height of the image is restricted. #media will allow for responsiveness based on browser height.
Higher resolution browsers will show the image at 900px height; those with a minimum of 700px height will show it at 600px, and smaller ones will show it at 400px.
You can of course adjust the numbers as per your preference; but this solution worked and solves the problem of long images.
Here's a jsfiddle. Note that using data-featherlight="image" is important for this to work properly.
Hope it helps.
In my opinion, the easiest way to both fit an image in the container and to center it is absolute positioning with margin: auto:
.featherlight img {
max-width:90%;
max-height:90%;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;
}
(Fiddle)
Alternatively, you can try to set the size of the image in viewport relative units (vw/vh), they have quite good browser support now: http://caniuse.com/#search=vw
Note: The following appears to be true only for Chrome, but it doesn't work in Firefox or IE...
After much twiddling around, my conclusion is that there's a fundamental difference in the way that height and width are treated in general and that it affects calculations here.
It's bound to be related to the flow of things, like how reducing the width of a <div> will have the content flow down, expanding the height, but how reducing the height of a <div> won't make it wider.
The clipping here is due to the fact that the border-bottom and padding-top are not taken into account in the available height. The solution is thus to remove those altogether.
If one still wants a border, then it can be faked by adding an absolutely positioned <div>. Here's the corresponding fiddle.
It gets cut off because the padding is throwing it off.
It doesn't work in IE or Firefox because they don't assume that the height of content div should stretch to fit its container's height. You would have to use height: 100% or some other percentage. This causes more problems when trying to achieve a max-height.
It doesn't enlarge the image when the size gets larger in height because that is the way most browsers handle re-rendering the page (or not re-rendering in this case) when the size of the viewport changes in height. You will have to force a re-rendering of the page. The only CSS way I know how to do that is with a CSS3 animation.
Here is a solution that does not work in Firefox or IE (so... not that great of a solution), but it fixes the cutting-off and resizing issues.
http://jsfiddle.net/SombreErmine/ENrnu/5/
It utilizes calc() and CSS3 animations; so it's definitely limited in practical use. I'm not posting this as the solution. I'm mostly posting it to share some information on what I've learned. Hopefully, this will help lead to a real solution.
HTML Code:
<div class="featherlight" style="display: block;">
<div class="featherlight-content">
<img src="http://placekitten.com/640/480" alt="" class="featherlight-image featherlight-inner"/>
</div>
</div>
CSS Code:
.featherlight {
position:fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
text-align: center;
background: rgba(0, 0, 0, 0.8);
}
.featherlight:before {
/* position: trick to center content vertically */
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em;
}
.featherlight .featherlight-content {
padding: 25px;
position: relative;
text-align: center;
vertical-align: middle;
display: inline-block;
min-width: 30%;
margin-left: 5%;
margin-right: 5%;
max-height: 95%;
background: #fff;
}
.featherlight .featherlight-image {
max-width:100%;
max-height:calc(100% - 50px);
vertical-align: bottom;
-webkit-animation: render_update 1s linear 0s infinite;
-moz-animation: render_update 1s linear 0s infinite;
-o-animation: render_update 1s linear 0s infinite;
animation: render_update 1s linear 0s infinite;
}
#-webkit-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#-moz-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#-o-keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
#keyframes render_update { from { padding-bottom: 0.001px; } to { padding-bottom: 0px; } }
You can try the following approach. Elements that have a set width become wider when they have padding and/or border-width. To avoid these problems, make use of the now common box-sizing: border-box; reset.
*,
*:before,
*:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
An element can be centered by setting height: 100%; to a "ghost" element (it can be a pseudo element) inside the parent and vertical-align: middle; to both.
.featherlight {
background-color: rgba(0, 0, 0, 0.8);
bottom: 0;
font-size: 0;
left: 0;
overflow: auto;
padding: 0 5%;
position: absolute;
right: 0;
text-align: center;
top: 0;
}
.featherlight:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
.featherlight-content {
display: inline-block;
margin: 5% 0;
max-width: 100%;
vertical-align: middle;
}
Images can be made responsive-friendly by applying max-width: 100%; and height: auto; to the image so that it scales nicely to the parent element.
.featherlight-content img {
border: 25px solid #fff;
display: block;
height: auto;
max-width: 100%;
}
See live example here: http://jsfiddle.net/cdog/AXzz8/.