I'm using some SVG's above and below a div to create an interesting shape that also scales well on small screens. A reduced test case can be seen here:
https://codepen.io/jciw/pen/eYWEazp
The SVG seems to align perfectly sometimes, but when resizing you can see a small (1px) gap between the SVG and the above or below div (to the left and the right). I'm assuming this is a rounding error, but is it solvable?
Reduced test case code:
<div class="container">
<svg class="homepage-rect-top" width="566" height="55" viewBox="0 0 566 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.81142 16.8646L554.811 54.484C560.592 54.883 565.5 50.3017 565.5 44.5078V0.5H0.5V6.88831C0.5 12.1439 4.5683 16.5026 9.81142 16.8646Z" fill="white"/>
</svg>
<div class="homepage-rectangle">
</div>
<svg class="homepage-rect-bottom" width="566" height="55" viewBox="0 0 566 55" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.81142 16.8646L554.811 54.484C560.592 54.883 565.5 50.3017 565.5 44.5078V0.5H0.5V6.88831C0.5 12.1439 4.5683 16.5026 9.81142 16.8646Z" fill="white"/>
</svg>
</div>
body {
background: #999999;
}
.container {
max-width: 80%;
margin: 0 auto;
}
.homepage-rectangle {
background: white;
min-height: 300px;
}
.homepage-rect-bottom {
width: 100%;
height: auto;
display: block;
stroke: white;
}
.homepage-rect-top {
width: 100%;
height: auto;
display: block;
stroke: white;
transform: scaleY(-1);
margin-bottom: -5px;
}
.reverse-it {
transform: scaleX(-1);
}
.flip-reverse-it {
transform: scale(-1);
}
why don't you simply put this in .homepage-rect-bottom:
margin-top:-1px;
in .homepage-rect-top use
margin-bottom: -1px
Ah, I see, ok, well I wouldn't go for an svg in that case, I would play around with something of the likes of this, which you can play around with:
body {
background: #999999;
}
.container{
max-width: 80%;
padding-top: 1rem;
}
.panel--one {
width:100%;
height: 450px;
background: white;
transform: perspective(800px) rotateY(-15deg);
border-radius:2rem;
}
html:
<div class="container">
<div class="panel--one"></div>
</div>
This turned out to be what I think was a rounding issue when using transforms on the SVG's. When using non-transformed SVG's this wasn't an issue.
Related
I have two arrow images (previous / next) with the code here like this:
.fp-controlArrow {
position: absolute;
width: 32px; /* This can be added here so you don't have to set a width and height 2 times for each arrow, this will create one width for both arrows */
height: 32px; /* This does the same as above */
margin-top:-15px; /* This value must always be half of the height - This does the same as above */
z-index: 30;
top: 50%;
cursor: pointer;
}
.fp-controlArrow.fp-prev {
left:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e923133f8dc0bf994fc49_left-arrow.svg) no-repeat;
}
.fp-controlArrow.fp-next {
right:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e9231ec03b6c9682b540c_right-arrow.svg) no-repeat;
I would like when I hover over an arrow it a round transparent circle appeared behind the arrow like on this example:
enter image description here
how can I achieve this?
thank you!
padding: 1em;
border-radius: 50%;
background-color: rgba(200,200,200,0.5)
Add those lines to the .fp-controlArrow class That should do it.
Edit
Sorry, I didn't realize it was svg. You will have to inline the svg.
<div class="fp-controlArrow fp-prev">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-reactroot="">
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="1" stroke="#221b38" d="M16 20L8 12L16 4"></path>
</svg>
</div>
<div class="fp-controlArrow fp-next">
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-reactroot="">
<path stroke-linejoin="round" stroke-linecap="round" stroke-width="1" stroke="#221b38" d="M8 20L16 12L8 4"></path>
</svg>
</div>
.fp-controlArrow {
position: absolute;
width: 32px; /* This can be added here so you don't have to set a width and height 2 times for each arrow, this will create one width for both arrows */
height: 32px; /* This does the same as above */
margin-top:-15px; /* This value must always be half of the height - This does the same as above */
z-index: 30;
top: 50%;
cursor: pointer;
padding: 1em;
border-radius: 50%;
}
.fp-controlArrow:hover {
background: green;
background-color: rgba(200,200,200,0.5);
}
.fp-controlArrow.fp-prev {
left:0;
}
.fp-controlArrow.fp-next {
right:0;
Here is a codepen that demonstrates it.
Sorry, I didn't saw the space between : and hover.
.fp-controlArrow.fp-prev {
left:0;
background: url(https://uploads-ssl.webflow.com/602dbecd2160ce28b5bc428b/602e923133f8dc0bf994fc49_left-arrow.svg) no-repeat;
border-radius: 50px;
}
.fp-controlArrow.fp-prev:hover{
background-color: #999999;
}
I've created a SVG icon component which wraps SVG icons inside a parent element using the following code:
HTML
<div class="icon-wrapper">
<svg class="icon">
<!--
The "icon-search" symbol comes from a SVG sprite in the doc body.
See live demo below...
-->
<use xlink:href="#icon-search"></use>
</svg>
</div>
CSS
body {
font-size: 48px;
color: black;
}
.icon-wrapper {
background-color: lightgreen;
}
.icon {
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
background-color: red;
}
Even though the height of the wrapping div is set to auto (its initial value) it somehow adds some padding to its bottom and is therefore a few pixels taller than the surrounded SVG. The green area shouldn't be there:
Why is this?
Here's a live example you can play with: https://jsbin.com/huyojeniwi/1/edit?html,css,output
This is because svg image is inline element and the browser saves spase from bottom for such "long" symbols as "p", "q", "y".
There is several solutions to this:
First:
.icon { display: block; }
Second:
.icon-wrapper { font-size: 0; } .icon { font-size: 48px; }
Third
.icon-wrapper { line-heigth: 1em; } .icon { vertical-align: top }
This is happening because svg tag is inline-block element, setting line-height:0; to parent element will fix it.
Inline boxes inherit inheritable properties such as font-size, line-height etc from their block parent element , and creates space/margin.
For more info
body {
font-size: 48px;
color: black;
}
.icon-wrapper {
background-color: lightgreen;
line-height: 0;
}
.icon {
width: 1em;
height: 1em;
stroke-width: 0;
stroke: currentColor;
fill: currentColor;
background-color: red;
}
<!-- Inlined SVG sprite -->
<svg style="position: absolute; width: 0; height: 0; overflow: hidden;" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-search" viewBox="0 0 26 28">
<title>search</title>
<path d="M18 13c0-3.859-3.141-7-7-7s-7 3.141-7 7 3.141 7 7 7 7-3.141 7-7zM26 26c0 1.094-0.906 2-2 2-0.531 0-1.047-0.219-1.406-0.594l-5.359-5.344c-1.828 1.266-4.016 1.937-6.234 1.937-6.078 0-11-4.922-11-11s4.922-11 11-11 11 4.922 11 11c0 2.219-0.672 4.406-1.937 6.234l5.359 5.359c0.359 0.359 0.578 0.875 0.578 1.406z"></path>
</symbol>
</defs>
</svg>
<div class="icon-wrapper">
<svg class="icon">
<use xlink:href="#icon-search"></use>
</svg>
</div>
I am trying to develop a CSS box hover effect using HTML5 & CSS3 but I cannot get this to work. I would like to make an effect like seen below:
when the user is not hovering
when user is hovering
i.e. how can I make a blue triangle and turn it into a blue square when the user hovers over it using HTML5 and CSS3? I need this only using HTML5 & CSS3 and not using canvas.
This element work with canvas perfectly like as below
var ctx = document.getElementById("c").getContext("2d");
ctx.fillStyle = "#0000ff";
function normal() {
ctx.clearRect(0,0,256,256);
ctx.beginPath();
ctx.moveTo(256,256);
ctx.lineTo(256,0);
ctx.lineTo(0,0);
ctx.closePath();
ctx.fill(); bars()
ctx.fillStyle="#0000ff"; for (i=0;i
But I need only using HTML5 & CSS3 scripting languages
Using SVG: (the entire effect that you are looking for)
I know you've asked for HTML(5) + CSS(3) but you could also use a SVG path element to produce this effect like in the below snippet. (Note: This uses SVG animations and its browser support can be different compared to CSS animations.)
svg {
height: 150px;
width: 150px;
stroke: black;
}
#blue {
stroke: blue;
stroke-width: 10;
}
svg polygon {
fill: blue;
}
#white {
stroke: white;
stroke-width: 10;
}
#icon {
fill: transparent;
}
<svg viewBox='0 0 100 100'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 1,0 1,1 0,0z'>
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,0z" to="M0,0 1,0 1,1 0,1z" dur="1s" begin="icon.mouseover" fill="freeze" />
<animate attributeType="XML" attributeName="d" from="M0,0 1,0 1,1 0,1z" to="M0,0 1,0 1,1 0,0z" dur="1s" begin="icon.mouseout" fill="freeze" />
</path>
</clipPath>
<g id='lines'>
<line x1='20' y1='30' x2='80' y2='30' />
<line x1='20' y1='50' x2='80' y2='50' />
<line x1='20' y1='70' x2='80' y2='70' />
</g>
</defs>
<use xlink:href='#lines' id='blue' />
<g clip-path='url(#clipper)'>
<polygon points='0,0 0,100 100,100 100,0' />
<use xlink:href='#lines' id='white' />
</g>
<g>
<polygon points='0,0 0,100 100,100 100,0' id='icon' />
</g>
</svg>
The below are answers to the question - how to turn triangle into square with animation.
Using Borders:
You could do it using border like in the below snippet. Initially only the right and top borders have the blue color but on hover we set the color to all border sides. This method is pretty simple and will work in all browsers (including IE8) but you cannot add content directly to this div (as doing so will affect the triangle shape) and so you'd have to place content on top of the shape using positioning or set the shape using a pseudo-element.
.shape{
height: 0px;
width: 0px;
border: 50px solid transparent;
border-color: blue blue transparent transparent;
transition: all 1s;
}
.shape:hover{
border-color: blue;
}
<div class='shape'></div>
Using Transforms:
You could add rotate transform on a pseudo-element, set overflow: hidden on parent to produce the triangle and then reverse/nullify the transform on hover.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: calc(100% * 1.414); /* using Pythogras theorem */
width: calc(100% * 1.414); /* using Pythogras theorem */
transform: rotate(-45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: rotate(0deg);
}
<div class='shape'></div>
You could also use a skewX transform instead of a rotate transform if you wish to avoid calculating the height and width like in the previous snippet.
.shape {
position: relative;
height: 100px;
width: 100px;
overflow: hidden;
}
.shape:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
transform: skewX(45deg);
transform-origin: left top;
background: blue;
transition: all 1s;
}
.shape:hover:after {
transform: skewX(0deg);
}
<div class='shape'></div>
Using Gradients:
You could use linear-gradients to create a triangle and then turn it into a square on hover by doubling the background-size.
.shape{
height: 100px;
width: 100px;
background: linear-gradient(to bottom left, blue 49.5%, transparent 50.5%);
background-position: 100% 0%;
background-size: 100% 100%;
transition: all 1s;
}
.shape:hover{
background-size: 200% 200%; /* just double the background size on hover */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='shape'></div>
In spite of the complete answer from Harry, couldn't resist to post an answer with another approach, suggested by the image in the OP.
Let's use blend modes, and see what can be achieved (but with more limited support)
.test {
width: 200px;
height: 200px;
background-color: white;
display: inline-block;
background-image: linear-gradient(blue, blue), linear-gradient(blue, blue), linear-gradient(blue, blue);
background-size: 100px 30px;
background-repeaT: no-repeat;
background-position: center 30px, center center, center 140px;
border: solid 1px black;
position: relative;
overflow: hidden;
}
.test:after {
content: "";
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: linear-gradient(45deg, yellow 50%, transparent 50%);
mix-blend-mode: difference;
transition: all 1s;
}
.one:after {
transform-origin: bottom right;
}
.one:hover:after {
transform: rotate(-45deg);
}
.two:hover:after {
opacity: 0;
}
.three:after {
background: none;
box-shadow: -1000px 1000px 0px 1000px yellow;
transform-origin: top left;
transform: rotate3d(1,1,0,87deg);
}
.three:hover:after {
transform: rotate3d(1,1,0,0deg);
}
<div class="test one"></div>
<div class="test two"></div>
<div class="test three"></div>
the third one is a little bit tricky, and not quite perfect. But you get the idea.
Is it possible to create the shape produced by this Fiddle. But then with no JavaScript but CSS3 (with <div>) ?
Basically this:
for(var i = 0; i < coords.length; i += 1) {
if(coords[(i + 1)] != undefined) {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[(i + 1)].x, coords[(i + 1)].y);
ctx.stroke();
} else {
ctx.beginPath();
ctx.moveTo(coords[i].x, coords[i].y);
ctx.lineTo(coords[0].x, coords[0].y);
ctx.stroke();
}
}
So you have points that needs to connect to each other?
Use svg, if you don't want to use canvas.
<svg width="100" height="100">
<path d="M0 0 l100 10 l-40 90z" fill="none" stroke="black" stroke-width="2" />
</svg>
Path command for 8,8,10,10,30,30,49,10 would be M8 8 L10 10 L30 40 L49 10z.
<svg width="49" height="40" viewBox="0 0 50 41">
<path d="M8 8 L10 10 L30 40 L49 10z" fill="none" stroke="black" stroke-width="2" />
</svg>
To apply a click event to the shape, you could use pointer-events: all on #test.
#test {
pointer-events: all;
}
<svg width="49" height="40" viewBox="0 0 50 41">
<path id="test" d="M8 8 L10 10 L30 40 L49 10z" fill="none" onclick="alert('Works')" stroke="black" stroke-width="2" />
</svg>
Note: Posting this answer just because you asked with CSS3, but the complexity and possible calculation overhead involved in this approach is proof enough why CSS shouldn't be used for this. Please do not use this approach.
A bit of explanation on how this was achieved:
A div is created with top and right border (1px black) and the other two borders are set to none.
This div is then skewed a bit to make it appear as though the edge on the right side is a bit slanted.
Inside the shape, a pseudo-element with only a right border is created and it is also skewed to produce the diagonal line from the right-bottom to the left-top. Transform origin is set as right-bottom to avoid positioning overhead.
An anchor tag is added within the parent div and the overflow is set to hidden so that only the portion within the shape is clickable.
The user select on the anchor tag are disabled to prevent a double click from selecting a blank space within the div.
Finally the whole container div is rotated a bit to make it look as though the triangle is not parallel to x-axis.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 50px;
width: 45px;
border: 1px solid black;
border-left: none;
border-bottom: none;
-webkit-transform: skew(-10deg) rotate(5deg);
-moz-transform: skew(-10deg) rotate(5deg);
transform: skew(-10deg) rotate(5deg);
overflow: hidden;
}
a {
display: block;
content: '';
margin-left: 0px;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
height: 100%;
width: 100%;
}
div:after {
position: absolute;
top: 0px;
left: 0px;
content: '';
height: 50px;
width: 45px;
-webkit-transform: skew(42deg);
-webkit-transform-origin: left bottom;
-moz-transform: skew(42deg);
-moz-transform-origin: left bottom;
transform: skew(42deg);
transform-origin: left bottom;
border-right: 1px solid black;
}
<div>
</div>
Another option to create a skewed triangle shape would be to use clip-path like in below snippet. The shape is created by applying the same clip-path on the main container element and a pseudo-element which is smaller than the container.
document.getElementById("clickme").onclick = function() {
alert('Hi! I work alright.');
}
div {
position: relative;
height: 150px;
width: 150px;
background: black;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
div:after{
position: absolute;
content: '';
height: calc(100% - 5px);
width: calc(100% - 5px);
top: 2px;
left: 3px;
background: white;
-webkit-clip-path: polygon(0% 0%, 100% 20%, 70% 100%);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 250px;
}
<div id="clickme"></div>
You can do it by embeding SVG as CSS. Quote from:
http://css-tricks.com/using-svg/
"Another way to use SVG's is to convert them into Data URI's. Data URI's might not save you actual file size, but can be more efficient because the data is right there. It doesn't require an additional HTTPRequest.
Mobilefish.com has an online conversion tool for that (http://www.mobilefish.com/services/base64/base64.php). Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back.
...
You can use that anywhere we've talked about so far (except inline because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.
As CSS
.logo {
background: url(data:image/svg+xml;base64,[data]);
}
"
I need to create an HTML page as shown in the following image.
I don't know how to create clickable forms containing text.
The text should not be an image and not exceed its area (like an overflow: hidden)
I tried areas and maps in HTML but it is not possible to put text inside.
How to do that please ?
EDIT :
I tried something else with SVG after reading the Phrogz's answers but my text is out of my triangle ? I don't understand why.
Demo (check at the bottom) :
http://jsfiddle.net/r7Jyy/3/
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="960px" height="560px"
viewBox="0 0 960 560"
style="enable-background:new 0 0 960 560;" xml:space="preserve">
<g>
<polygon style="fill-rule:evenodd;clip-rule:evenodd;fill:none;" points="524.131,495.773 524.771,495.615 524.179,495.282 "/>
<polygon style="fill-rule:evenodd;clip-rule:evenodd;fill:#CCC;" points="569.476,-10 212.575,320.5 524.179,495.282 572.75,-1.521 "/>
</g>
<text transform="matrix(1 0 0 1 236 255)">
<tspan x="0" y="0" style="fill:#888; font-family:'Arial'; font-size:36.0467;">500% </tspan>
<tspan x="0" y="30.039" style="fill:#888; font-family:'Arial'; font-size:36.0467;">New</tspan>
</text>
</svg>
Here's an SVG example using clipping paths to clip text to arbitrary regions:
Demo: http://jsfiddle.net/r7Jyy/
<svg xmlns="http://www.w3.org/2000/svg">
<defs><clipPath id="triangle1">
<polygon points="10,30 180,60 250,10"/>
</clipPath></defs>
<polygon points="10,30 180,60 250,10" fill="none" stroke="black"/>
<text x="20" y="50" clip-path="url(#triangle1)">Hello World</text>
</svg>
Use SVG's filter effects to create the embossed, inner shadow result on your text. Here's an example (that does not exactly match your needs): http://www.w3.org/2002/05/text.svg
You might want to give CSS3 a shot here ...
You should just make your code a bit more cross-browser ( e.g. adding -moz-transform, etc.. )
And have to try a bit harder to achieve inner-shadow of the letters, but you can do this with :
HTML :
<div class='container'>
<div class='text'>Hello<br />World<br /> I'm Steffi</div>
<div class='triangleA'></div>
<div class='triangleB'>
<div class='text'>
Can you <br />
Help Me Please</div>
</div>
<div class='triangleC'>
<div class='text'>
Stackover-<br />flow.com
</div>
</div>
</div>
and CSS :
.container {
position: absolute;
overflow: hidden;
width: 550px;
height: 500px;
background: #9f9f9f;
}
div.text {
font: bold 45px 'Helvetica';
text-align: left;
margin: 120px 0 0 180px;
line-height: 40px;
color: #3f3f3f;
text-transform: uppercase;
text-shadow: 0px 1px rgba(255,255,255,.4);
}
div.triangleA, div.triangleB, div.triangleC {
position: absolute;
}
div.triangleA {
background: #afafaf;
width: 500px;
height: 600px;
-webkit-transform: rotate(45deg);
top: -350px;
left: -230px;
}
div.triangleB {
background: rgba(255,255,255,.4);
overflow: hidden;
width: 500px;
height: 600px;
-webkit-transform: rotate(-70deg);
top: 200px;
left: -230px;
}
div.triangleB div.text {
-webkit-transform: rotate(70deg);
margin-left: 240px;
margin-top: 550px;
width: 500px;
}
div.triangleC {
background: #8f8f8f;
-webkit-transform: rotate(-25deg);
top: 370px;
left: 100px;
height: 300px;
width: 600px;
overflow: hidden;
}
div.triangleC div.text {
-webkit-transform: rotate(25deg);
margin: 0;
margin-left: 190px;
margin-top: 60px;
}
Demo : http://jsbin.com/orazod/1/edit