Background tile hatching animation - javascript

I have to template a design in which some of the content modules come with a hatching as a decoration element:
Modules and therefore the hatchings alike are responsive, so module and hatching come in all sizes and aspect ratios imaginable. Hatchings can have different positions, too:
Obviously, these hatchings are realized with a simple SVG background tile:
Here is the problem:
The design department came up with an animation for the hatching, where the lines start at different lengths and grow, until every line arrives at its final length:
Maybe I'm missing something obvious here, but I can't figure out how to build this responsively. Of course I could use a lottieFile or even a video, but these would scale line width and spaces responsively - and that's out of the question.
The design department already sold the animation to the customer, so I really have to find a way ... any suggestions?
EDIT: provided some sample code:
MORE EDIT: You have to switch to "Full page" when running the code snippet to see the correct rendering of the elements ... weird ...
.grid {
margin: 0 auto;
width: 75vw;
max-width: 800px;
height: 75vh;
display: grid;
grid-template-columns: 100px 1fr 100px;
grid-template-rows: 100px 1fr 100px;
}
.contentElement {
grid-column: 1 / 3;
grid-row: 1 / 3;
z-index: 2;
padding: 40px;
background-color: lightgray;
}
.hatching {
grid-column: 2 / 4;
grid-row: 2 / 4;
z-index: 1;
/* background-image: url(img/background/tile_hatching_l.svg); */
/* background-repeat: repeat; */
background-color: red;
}
<!-- grid -->
<div class="grid">
<div class="contentElement">
This is the content element
</div>
<div class="hatching"></div>
</div>
<!-- end grid -->

The hatches in this solution are a only pseudo-random and repeat every 20 lines. The pattern repeats every 200 px horizontally, but stretches vertically to the height of the wrapping <svg> element. Each line is initially vertical, and only after the pattern is fitted it is skewed so the lines appear to be diagonal.
document.querySelector('button').addEventListener('click', ()=> {
document.querySelector('#hatches path').classList.add('full');
})
#hatches path {
fill:none;
stroke:red;
stroke-width:1;
transition: d 1s linear;
}
#hatches path.full {
d: path('M 5,0 5,100 M 15,0 15,100 M 25,0 25,100 M 35,0 35,100 M 45,0 45,100 M 55,0 55,100 M 65,0 65,100 M 75,0 75,100 M 85,0 85,100 M 95,0 95,100 M 105,0 105,100 M 115,0 115,100 M 125,0 125,100 M 135,0 135,100 M 145,0 145,100 M 155,0 155,100 M 165,0 165,100 M 175,0 175,100 M 185,0 185,100 M 195,0 195,100')
}
rect { fill: url(#hatches) }
<svg width="400" height="300">
<pattern id="hatches" width="200" height="100%" patternUnits="userSpaceOnUse" viewBox="0 0 200 100" preserveAspectRatio="none" patternTransform="skewX(-45)">
<path d='M5,37 5,91 M 15,40 15,80 M 25,11 25,59 M 35,26 35,79 M 45,29 45,83 M 55,50 55,98 M 65,20 65,59 M 75,7 75,99 M 85,17 85,56 M 95,33 95,55 M 105,20 105,67 M 115,45 115,55 M 125,18 125,93 M 135,33 135,89 M 145,20 145,98 M 155,14 155,62 M 165,45 165,64 M 175,3 175,53 M 185,20 185,73 M 195,30 195,59' />
</pattern>
<rect width="100%" height="100%" />
</svg>
<button>Fill</button>

Related

Trasparent text in an html a-href button with a threejs animation in background [duplicate]

Is there any way to make a transparent text cut out of a background effect like the one in the following image, with CSS?
It would be sad to lose all precious SEO because of images replacing text.
I first thought of shadows but I can't figure anything out...
The image is the site background, an absolute positioned <img> tag
It's possible with css3 but it's not supported in all browsers
With background-clip: text; you can use a background for the text, but you will have to align it with the background of the page
body {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
margin:10px;
}
h1 {
background-color:#fff;
overflow:hidden;
display:inline-block;
padding:10px;
font-weight:bold;
font-family:arial;
color:transparent;
font-size:200px;
}
span {
background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
display:block;
}
<h1><span>ABCDEFGHIKJ</span></h1>
http://jsfiddle.net/JGPuZ/1337/
Automatic Alignment
With a little javascript you can align the background automatically:
$(document).ready(function(){
//Position of the header in the webpage
var position = $("h1").position();
var padding = 10; //Padding set to the header
var left = position.left + padding;
var top = position.top + padding;
$("h1").find("span").css("background-position","-"+left+"px -"+top+"px");
});
body {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
margin:10px;
}
h1 {
background-color:#fff;
overflow:hidden;
display:inline-block;
padding:10px;
font-weight:bold;
font-family:arial;
color:transparent;
font-size:200px;
}
span {
background: url(http://www.color-hex.com/palettes/26323.png) -20px -20px repeat;
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1><span>ABCDEFGHIKJ</span></h1>
​
http://jsfiddle.net/JGPuZ/1336/
Although this is possible with CSS, a better approach would be to use an inline SVG with SVG masking. This approach has some advantages over CSS :
Much better browser support: IE10+, chrome, Firefox, safari...
This doesn't impact SEO as spiders can crawl SVG content (google indexes SVG content since 2010)
CodePen Demo : SVG text mask
body,html{height:100%;margin:0;padding:0;}
body{
background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
background-size:cover;
background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
<defs>
<mask id="mask" x="0" y="0" width="100" height="50">
<rect x="0" y="0" width="100" height="40" fill="#fff"/>
<text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
<text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
</mask>
</defs>
<rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>
</svg>
If you aim on making the text selectable and searchable, you need to include it outside the <defs> tag. The following example shows a way to do that keeping the transparent text with the <use> tag:
body,html{height:100%;margin:0;padding:0;}
body{
background:url('https://farm9.staticflickr.com/8760/17195790401_94fcf60556_c.jpg');
background-size:cover;
background-attachment:fixed;
}
svg{width:100%;}
<svg viewbox="0 0 100 60">
<defs>
<g id="text">
<text text-anchor="middle" x="50" y="18" dy="1">SVG</text>
<text text-anchor="middle" x="50" y="30" dy="1">Text mask</text>
</g>
<mask id="mask" x="0" y="0" width="100" height="50">
<rect x="0" y="0" width="100" height="40" fill="#fff"/>
<use xlink:href="#text" />
</mask>
</defs>
<rect x="5" y="5" width="90" height="30" mask="url(#mask)" fill-opacity="0.5"/>
<use xlink:href="#text" mask="url(#mask)" />
</svg>
There is a simple way to do this with just CSS:
background: black;
color: white;
mix-blend-mode: multiply;
for transparent text on a black background, or
background: white;
color: black;
mix-blend-mode: screen;
for transparent text on a white background.
Put these styles on your text element with whichever background you want behind it.
Example CodePen
Read up on mix-blend-mode and experiment with it to use different colours.
Caveats:
For this to work in chrome, you also need to explicitly set a background colour on the html element.
This works on basically all modern browsers except IE.
It is possible, but so far only with Webkit based browsers (Chrome, Safari, Rockmelt, anything based on the Chromium project.)
The trick is to have an element within the white one that has the same background as the body, then use -webkit- background-clip: text; on the inner element which basically means "don't extend the background beyond the text" and use transparent text.
section
{
background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
width: 100%;
height: 300px;
}
div
{
background: rgba(255, 255, 255, 1);
color: rgba(255, 255, 255, 0);
width: 60%;
heighT: 80%;
margin: 0 auto;
font-size: 60px;
text-align: center;
}
p
{
background: url(http://norcaleasygreen.com/wp-content/uploads/2012/11/turf-grass1.jpg);
-webkit-background-clip: text;
}
​
http://jsfiddle.net/BWRsA/
just put that css
.banner-sale-1 .title-box .title-overlay {
font-weight: 900;
overflow: hidden;
margin: 0;
padding-right: 10%;
padding-left: 10%;
text-transform: uppercase;
color: #080404;
background-color: rgba(255, 255, 255, .85);
/* that css is the main think (mix-blend-mode: lighten;)*/
mix-blend-mode: lighten;
}
I just discovered a new way to do this while messing around, I'm not entirely sure how it works ( if someone else wants to explain please do ).
It seems to work very well, and requires no double backgrounds or JavaScript.
Here's the code:
JSFIDDLE
body {
padding: 0;
margin: 0;
}
div {
background: url(http://www.color-hex.com/palettes/26323.png) repeat;
width: 100vw;
height: 100vh;
}
body::before {
content: '$ALPHABET';
left: 0;
top: 0;
position: absolute;
color: #222;
background-color: #fff;
padding: 1rem;
font-family: Arial;
z-index: 1;
mix-blend-mode: screen;
font-weight: 800;
font-size: 3rem;
letter-spacing: 1rem;
}
<div></div>
In the near future we can use element() to achieve this
The element() function allows an author to use an element in the document as an image. As the referenced element changes appearance, the image changes as well ref
The trick is to create a common div with text then use element() combined with mask.
Here is a basic example that works only on the latest version Firefox for now.
#text {
font-size:35px;
font-weight:bold;
color:#000;
font-family:sans-serif;
text-transform: uppercase;
white-space:nowrap;
/* we hide it */
position:fixed;
right:200vw;
bottom:200vh
}
body {
background:url(https://picsum.photos/id/1018/800/800) center/cover;
}
.main {
margin:50px;
height:100px;
background:red;
-webkit-mask:
-moz-element(#text) center/contain no-repeat, /* this behave like a background-image*/
linear-gradient(#fff 0 0);
mask-composite:exclude;
}
<div id="text">
You can put your text here
</div>
<div class="main">
</div>
It will produce the following:
It's reponsive since we rely on basic background properties and we can easily update the text using basic CSS.
We can consider any kind of content and also create patterns:
#text {
font-size:30px;
font-weight:bold;
color:#000;
font-family:sans-serif;
text-transform: uppercase;
white-space:nowrap;
padding:20px;
/* we hide it */
position:fixed;
right:200vw;
bottom:200vh
}
#text span {
font-family:cursive;
font-size:35px;
}
body {
background:url(https://picsum.photos/id/1018/800/800) center/cover;
}
.main {
margin:50px;
height:100px;
background:red;
-webkit-mask:
-moz-element(#text) 0 0/20% auto, /* this behave like a background-image*/
linear-gradient(#fff 0 0);
mask-composite:exclude;
}
<div id="text">
Your <span>text</span> here 👍
</div>
<div class="main">
</div>
And why not some animation to create an infinite scrolling text:
#text {
font-size:30px;
font-weight:bold;
color:#000;
font-family:sans-serif;
text-transform: uppercase;
white-space:nowrap;
padding:20px 5px;
/* we hide it */
position:fixed;
right:200vw;
bottom:200vh
}
body {
background:url(https://picsum.photos/id/1018/800/800) center/cover;
}
.main {
margin:50px;
height:100px;
padding-right:calc(50% - 50px);
background:red;
-webkit-mask:
-moz-element(#text) 0 50%/200% auto content-box, /* this behave like a background-image*/
linear-gradient(#fff 0 0);
mask-composite:exclude;
animation:m 5s linear infinite;
}
#keyframes m{
to {-webkit-mask-position:200% 50%}
}
<div id="text">
Srolling repeating text here
</div>
<div class="main">
</div>
I guess you could achieve something like that using background-clip, but I haven't tested that yet.
See this example:
http://www.css3.info/wp-content/uploads/2008/03/webkit-backgroundcliptext_color.html
(Webkit only, I don't know yet how to change the black background to a white one)
You can use an inverted / negative / reverse font and apply it with the font-face="…" CSS rule. You might have to play with letter spacing to avoid small white gaps between letters.
If you do not require a specific font, it's simple. Download a likeable one, for example from this collection of inverted fonts.
If you require a specific font (say, "Open Sans"), it's difficult. You have to convert your existing font into an inverted version. This is possible manually with Font Creator, FontForge etc., but of course we want an automated solution. I could not find instructions for that yet, but some hints:
How to convert a bitmap font into a TrueType font (plus yet another way to do that). One would first use ImageMagick commands to render the font glyphs into high-resolution raster images and to invert them, then convert them back to a TrueType font with the above instructions.
Is it possible to invert a font with FontForge or another PGM?
Creating a reverse (white on black) font
You can use myadzel's Patternizer jQuery plugin to achieve this effect across browsers. At this time, there is no cross-browser way to do this with just CSS.
You use Patternizer by adding class="background-clip" to HTML elements where you want the text to be painted as an image pattern, and specify the image in an additional data-pattern="…" attribute. See the source of the demo. Patternizer will create an SVG image with pattern-filled text and underlay it to the transparently rendered HTML element.
If, as in the question's example image, the text fill pattern should be a part of a background image extending beyond the "patternized" element, I see two options (untested, my favourite first):
Use masking instead of a background image in the SVG. As in web-tiki's answer, to which using Patternizer will still add automatic generation of the SVG and an invisible HTML element on top that allows text selection and copying.
Or use automatic alignment of the pattern image. Can be done with JavaScript code similar to the one in Gijs's answer.
I needed to make text that looked exactly like it does in the original post, but I couldn't just fake it by lining up backgrounds, because there's some animation behind the element. Nobody seems to have suggested this yet, so here's what I did: (Tried to make it as easy to read as possible.)
var el = document.body; //Parent Element. Text is centered inside.
var mainText = "THIS IS THE FIRST LINE"; //Header Text.
var subText = "THIS TEXT HAS A KNOCKOUT EFFECT"; //Knockout Text.
var fontF = "Roboto, Arial"; //Font to use.
var mSize = 42; //Text size.
//Centered text display:
var tBox = centeredDiv(el), txtMain = mkDiv(tBox, mainText), txtSub = mkDiv(tBox),
ts = tBox.style, stLen = textWidth(subText, fontF, mSize)+5; ts.color = "#fff";
ts.font = mSize+"pt "+fontF; ts.fontWeight = 100; txtSub.style.fontWeight = 400;
//Generate subtext SVG for knockout effect:
txtSub.innerHTML =
"<svg xmlns='http://www.w3.org/2000/svg' width='"+stLen+"px' height='"+(mSize+11)+"px' viewBox='0 0 "+stLen+" "+(mSize+11)+"'>"+
"<rect x='0' y='0' width='100%' height='100%' fill='#fff' rx='4px' ry='4px' mask='url(#txtSubMask)'></rect>"+
"<mask id='txtSubMask'>"+
"<rect x='0' y='0' width='100%' height='100%' fill='#fff'></rect>"+
"<text x='"+(stLen/2)+"' y='"+(mSize+6)+"' font='"+mSize+"pt "+fontF+"' text-anchor='middle' fill='#000'>"+subText+"</text>"+
"</mask>"+
"</svg>";
//Relevant Helper Functions:
function centeredDiv(parent) {
//Container:
var d = document.createElement('div'), s = d.style;
s.display = "table"; s.position = "relative"; s.zIndex = 999;
s.top = s.left = 0; s.width = s.height = "100%";
//Content Box:
var k = document.createElement('div'), j = k.style;
j.display = "table-cell"; j.verticalAlign = "middle";
j.textAlign = "center"; d.appendChild(k);
parent.appendChild(d); return k;
}
function mkDiv(parent, tCont) {
var d = document.createElement('div');
if(tCont) d.textContent = tCont;
parent.appendChild(d); return d;
}
function textWidth(text, font, size) {
var canvas = window.textWidthCanvas || (window.textWidthCanvas = document.createElement("canvas")),
context = canvas.getContext("2d"); context.font = size+(typeof size=="string"?" ":"pt ")+font;
return context.measureText(text).width;
}
Just throw that in your window.onload, set the body's background to your image, and watch the magic happen!
mix-blend-mode is also a possibility for that kind of effect .
The mix-blend-mode CSS property sets how an element's content should blend with the content of the element's parent and the element's background.
h1 {
background:white;
mix-blend-mode:screen;
/* demo purpose from here */
padding:0.25em;
mix-blend-mode:screen;
}
html {
background:url(https://i.picsum.photos/id/1069/367/267.jpg?hmac=w5sk7UQ6HGlaOVQ494mSfIe902cxlel1BfGUBpEYoRw)center / cover ;
min-height:100vh;
display:flex;
}
body {margin:auto;}
h1:hover {border:dashed 10px white;background-clip:content-box;box-shadow:inset 0 0 0 2px #fff, 0 0 0 2px #fff}
<h1>ABCDEFGHIJKLMNOPQRSTUVWXYZ</h1>
This worked for me mix-blend-mode: color-dodge on the container with opposite colors.
.main{
background: url('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg');
height: 80vh;
width: 100vw;
padding: 40px;
}
.container{
background-color: white;
width: 80%;
height: 50px;
padding: 40px;
font-size: 3em;
font-weight: 600;
mix-blend-mode: color-dodge;
}
.container span{
color: black;
}
<div class="main">
<div class="container">
<span>This is my text</span>
</div>
</div>
Not possible with CSS just now I'm afraid.
Your best bet is to simply use an image (probably a PNG) and and place good alt/title text on it.
Alternatively you could use a SPAN or a DIV and have the image as a background to that with your text you want for SEO purposes inside it but text-indent it off screen.

CSS how to make an effect of a hand holding cards

So basically i want to have an transparent image of a hand holding cards, then i want to display cards on a curve like when you are holding 10 cards in your hand (not fixed 10 of course). So they should be positioned on a curved dome.
I'm working in angular, and i know that i have to accomplish this via position absolute and transform: translate-rotate css, just don't know how
I'm also working with bootstrap so this image with cards should be in a col-12 and compatible on a smaller screens.
I only have the parts of the code that i took from a guy that positioned elements in a circle - Bootstrap 3 align elements into circle
i tried to play around with translate and rotate but couldn't get it working
Here's the way I approached it. There's alot going on here, but it's basically
setting a overall width to work with
using a predefined number of cards and overall angle allowance
using math to distribute and angle the cards
using transform-origin: bottom center; to give the effect
let cards = document.querySelector('.cards');
let w = cards.offsetWidth;
let totalarc = 270;
let numcards = 7;
let angles = Array(numcards).fill('').map((a, i) => (totalarc / numcards * (i + 1)) - (totalarc/2 + (totalarc / numcards) / 2));
let margins = angles.map((a, i) => w / numcards * (i + 1));
angles.forEach((a, i) => {
let s = `transform:rotate(${angles[i]}deg);margin-left:${margins[i]}px;`
let c = `<div class='card' style='${s}'></div>`;
cards.innerHTML += c;
})
.container {
position: relative;
margin-left: 80px;
width: 100%;
}
.cards {
width: 150px;
}
.card {
width: 120px;
height: 200px;
background: #999;
border: 1px solid #000;
position: absolute;
opacity: .5;
transform-origin: bottom center;
}
<div class='container'>
<div class='cards'></div>
<div class='hand'>
<div>
</div>

Make a div that go somewhat curved

This question have been asked a billion times I think, but just another case.
How to make this with HTML / CSS (and, if no other option, JS - I'm thinking of canvas or SVG) :
Notes : the div should be able to contain a scrolling background image on the whole green part. And this should work on IE9+ and common mobile devices (default browser). Also, the space around the shape needs to stay transparent (no white element to create the rounded shape can be used)
What's the better option ?
CSS Implementation
You can create a border shape within a container and hide the unwanted parts. I have used view port sized units to be scalable. It can be further improved to your requirement by manipulating with the values.
body {
background: #F5F5F5;
}
.container {
height: 70vh;
overflow: hidden;
display: inline-block;
width: 30vh;
background: white;
margin: 0 10px;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
}
.curve {
background: transparent;
border: 20vh solid #7cc576;
border-radius: 35%;
height: 100vh;
transform: translateY(-20vh);
width: 50vh;
}
.container-left-curved {
transform: rotateY(180deg);
}
.container-right-curved {
transform: rotateY(0deg);
}
<div class="container container-left-curved">
<div class="curve">
</div>
</div>
<div class="container container-right-curved">
<div class="curve">
</div>
</div>
SVG Implementation
I saved your image and generated the optimized SVG code through Inkscape editor. This looks a lot better than a pure CSS solution.
body {
background: lightgray;
}
<svg height="300px" width="200px" version="1.1" viewBox="0 0 492 746.00001" fill="#000">
<g id="layer1" transform="translate(-119.71 -187.93)">
<path id="path3349" d="m189.71 620.93c0-206.67-0.33548-311-1-311-0.55 0-1-2.25-1-5s-0.45-5-1-5-1-1.9984-1-4.441c0-2.4425-0.45-4.7191-1-5.059-0.55-0.33992-1-1.9415-1-3.559s-0.45-2.941-1-2.941-1-1.0984-1-2.441c0-1.3425-0.45-2.7191-1-3.059-0.55-0.33992-1-1.9415-1-3.559s-0.45-2.941-1-2.941-1-0.88631-1-1.9696-0.9-3.572-2-5.5304c-1.1-1.9585-2-4.2222-2-5.0304 0-0.80827-0.45-1.4696-1-1.4696s-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.9-1-2-0.45-2-1-2-1-0.59015-1-1.3114c0-0.72129-0.9-2.2775-2-3.4582s-2-2.7323-2-3.448-0.9-1.8633-2-2.5503c-1.1-0.68696-2-2.0459-2-3.0198 0-0.97393-0.9-2.4195-2-3.2123-1.1-0.79284-2.0021-1.9047-2.0046-2.4708-0.002-0.56608-1.3525-2.4673-3-4.225-1.6474-1.7577-3-3.5577-3.0056-4-0.006-0.44232-2.2557-3.1613-5-6.0422-2.7444-2.8809-4.9897-5.6545-4.9897-6.1636 0-0.50907-2.534-3.4395-5.6312-6.512l-5.6312-5.5864h207.31 207.31l11.311 11.25c6.2212 6.1875 11.317 11.7 11.325 12.25 0.007 0.55 1.788 2.8 3.9571 5s3.9659 4.7875 3.9929 5.75 0.52562 1.75 1.1081 1.75c0.58246 0 0.73793 0.51953 0.34549 1.1545-0.39555 0.64-0.27852 0.88566 0.2626 0.55123 0.98336-0.60775 4.3329 2.601 4.3329 4.1507 0 0.45847 0.9 1.6481 2 2.6436 1.1 0.99549 2 2.6402 2 3.655s0.45 1.845 1 1.845 1 0.59015 1 1.3114c0 0.72129 0.9 2.2775 2 3.4582s2 2.8406 2 3.6886c0 0.84799 0.45 1.5418 1 1.5418s1 0.9 1 2 0.45 2 1 2 1 0.9 1 2 0.45 2 1 2 1 0.9 1 2 0.47656 2 1.059 2c0.58246 0 0.81241 0.39901 0.51101 0.88669-0.30141 0.48768 0.12204 1.4428 0.94098 2.1224 0.81894 0.67966 1.489 2.0806 1.489 3.1133s0.45 1.8776 1 1.8776 1 1.35 1 3 0.45 3 1 3 1 1.1516 1 2.559c0 1.4514 0.43284 2.2915 1 1.941 0.58342-0.36057 1 0.65628 1 2.441 0 1.6825 0.45 3.059 1 3.059s1 1.8 1 4 0.45 4 1 4 1 1.8 1 4 0.45 4 1 4 1 2.25 1 5 0.45 5 1 5c0.66452 0 1 104 1 310v310h-210-210v-311z"
fill="#7ac474" />
</g>
</svg>
Finally, after looking for the good way to achieve that, here's my notes:
1. RaphaelJS
I think RaphaelJS makes it easy and offers extended compatibility (I tested on IE8 and IE7, it works, even if I don't need it) and easier manipulation.
Here's a live example : http://jsfiddle.net/bkfssykp/
As you can see, this is somewhat a SVG based solution :
paper.path("M0,0h259.478c0,0,42.939,36.419,42.939,88.694 c0,132.905,0,368.306,0,368.306H42.939c0,0,0-235.587,0-368.464C42.939,36.345,0,0,0,0z");
I just pasted the code of my svg shape directly into it. Now, I can play with it : animation, modification, etc.
2. SVG clip-path
My first attempt was an SVG image with a SVG clip-path, as said in the article mentionned by #Deepak : https://css-tricks.com/clipping-masking-css/
Here's a live example : http://jsfiddle.net/xptycnkg/3/
Still SVG : this looks like CSS clip-path, but applied on SVG element. Works on IE9.

How to crop background images

I am trying to crop background image with custom form.. but I have stacked with that.
The goal is to crop image like this:
Think of every step like it is different html pages (page-1.html, page-2.html, page-3.html).
In the page-1.html background is pretty simple. The important think to admit - this pictures have to be responsive.
page-1.html
background-image: url(image-1.jpg) no-repeat 50% 0;
background-size: cover;
The second example can be done by using <svg> elements.
page-2.html
<svg id="bigTriangleColor" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="200" viewBox="0 0 100 102" preserveAspectRatio="none" class="triangle-svg">
<path d="M0 100 L50 0 L100 100 Z"></path>
</svg>
<style>
.triangle-svg {
position: absolute;
left: 0;
right: 0;
top: auto;
bottom: 0;
z-index: 999;
fill: #fff;
}
</style>
But what about third example? I don't know how to deal with it.
In 3 example we see something like:
<div class='top-layout'></div>
<div class='bottom-layout'></div>
The .top-layout image should be croped. The <svg> decision is bad because we should able to put second image uderneeth the first.
.top-layout {
height: 500px;
}
.bottom-layout {
height: 500px;
position: relative;
top: -150px;
}
And all this stuff should be responsive with background-size: conver effect.
#phrogz deserve all the credits since he answered first.
Demo of clip-path, mask and gradient. For your solution, replace the contents of group <g clip-path="url(#clip-bottom)" > ... </g> with your own <image .... clip-path="url(#clip-bottom)" />. Usually I'd create a group with clip-path to keep the image tag cleaner, but that's my own preference.

How to add a tooltip to an svg graphic?

I have a series of svg rectangles (using D3.js) and I want to display a message on mouseover, the message should be surrounded by a box that acts as background. They should both be perfectly aligned to each other and to the rectangle (on top and centered). What is the best way to do this?
I tried adding an svg text using the "x", "y", "width" and "height" attributes, and then prepending an svg rect. The problem is that the reference point for the text is in the middle (since I want it centered aligned I used text-anchor: middle), but for the rectangle it's the top left coordinate, plus I wanted a bit of margin around the text which makes it kind of a pain.
The other option was using an html div, which would be nice, because I can add the text and padding directly but I don't know how to get the absolute coordinates for each rectangle. Is there a way to do this?
Can you use simply the SVG <title> element and the default browser rendering it conveys? (Note: this is not the same as the title attribute you can use on div/img/spans in html, it needs to be a child element named title)
rect {
width: 100%;
height: 100%;
fill: #69c;
stroke: #069;
stroke-width: 5px;
opacity: 0.5
}
<p>Mouseover the rect to see the tooltip on supporting browsers.</p>
<svg xmlns="http://www.w3.org/2000/svg">
<rect>
<title>Hello, World!</title>
</rect>
</svg>
Alternatively, if you really want to show HTML in your SVG, you can embed HTML directly:
rect {
width: 100%;
height: 100%;
fill: #69c;
stroke: #069;
stroke-width: 5px;
opacity: 0.5
}
foreignObject {
width: 100%;
}
svg div {
text-align: center;
line-height: 150px;
}
<svg xmlns="http://www.w3.org/2000/svg">
<rect/>
<foreignObject>
<body xmlns="http://www.w3.org/1999/xhtml">
<div>
Hello, <b>World</b>!
</div>
</body>
</foreignObject>
</svg>
…but then you'd need JS to turn the display on and off. As shown above, one way to make the label appear at the right spot is to wrap the rect and HTML in the same <g> that positions them both together.
To use JS to find where an SVG element is on screen, you can use getBoundingClientRect(), e.g. http://phrogz.net/svg/html_location_in_svg_in_html.xhtml
The only good way I found was to use Javascript to move a tooltip <div> around. Obviously this only works if you have SVG inside an HTML document - not standalone. And it requires Javascript.
function showTooltip(evt, text) {
let tooltip = document.getElementById("tooltip");
tooltip.innerHTML = text;
tooltip.style.display = "block";
tooltip.style.left = evt.pageX + 10 + 'px';
tooltip.style.top = evt.pageY + 10 + 'px';
}
function hideTooltip() {
var tooltip = document.getElementById("tooltip");
tooltip.style.display = "none";
}
#tooltip {
background: cornsilk;
border: 1px solid black;
border-radius: 5px;
padding: 5px;
}
<div id="tooltip" display="none" style="position: absolute; display: none;"></div>
<svg>
<rect width="100" height="50" style="fill: blue;" onmousemove="showTooltip(evt, 'This is blue');" onmouseout="hideTooltip();" >
</rect>
</svg>
You can use the title element as Phrogz indicated. There are also some good tooltips like jQuery's Tipsy http://onehackoranother.com/projects/jquery/tipsy/ (which can be used to replace all title elements), Bob Monteverde's nvd3 or even the Twitter's tooltip from their Bootstrap http://twitter.github.com/bootstrap/
On svg, the right way to write the title
<svg>
<title id="unique-id">Checkout</title>
</svg>
check here for more details https://css-tricks.com/svg-title-vs-html-title-attribute/
I came up with something using HTML + CSS only. Hope it works for you
.mzhrttltp {
position: relative;
display: inline-block;
}
.mzhrttltp .hrttltptxt {
visibility: hidden;
width: 120px;
background-color: #040505;
font-size:13px;color:#fff;font-family:IranYekanWeb;
text-align: center;
border-radius: 3px;
padding: 4px 0;
position: absolute;
z-index: 1;
top: 105%;
left: 50%;
margin-left: -60px;
}
.mzhrttltp .hrttltptxt::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent #040505 transparent;
}
.mzhrttltp:hover .hrttltptxt {
visibility: visible;
}
<div class="mzhrttltp"><svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 24 24" fill="none" stroke="#e2062c" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-heart"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"></path></svg><div class="hrttltptxt">علاقه‌مندی‌ها</div></div>
I always go with the generic css title with my setup. I'm just building analytics for my blog admin page. I don't need anything fancy. Here's some code...
let comps = g.selectAll('.myClass')
.data(data)
.enter()
.append('rect')
...styling...
...transitions...
...whatever...
g.selectAll('.myClass')
.append('svg:title')
.text((d, i) => d.name + '-' + i);
And a screenshot of chrome...
I use heroicons for the project I am working on. (This is JSX format) I will handle the tooltip issue with this code.
<svg className="h-6 w-6">
<title>{reasons.join(" ")}</title>
<QuestionMarkCircleIcon className={style} />
</svg>

Categories