Related
I'm trying to rotate a graph made in SVG when the viewport is smaller than 600px. I used a media querie and it work great but the svg is overflowing from it's container and whatever I do, I can't fix it.
Is it possible to fix it without javascript ?
I tried to use the preserveAspectRatio attribute and the viewbox attribute but it doesnt work.
Here's the code : https://codepen.io/telumire-the-sasster/pen/vYBxLRg
HTML :
<div class="container">
<svg viewBox="0 0 700 100" preserveAspectRatio="none" class="graphic" style="">
<polyline fill="red" stroke="none"
points="
0,0
0,15
100,14
200,18
300,21
400,23
500,22
600,17
700,17
700,0
0,0
"/>
</svg>
</div>
CSS :
.container {
background-color: green;
}
.graphic {
transform: scaleY(-1);
}
#media (max-width: 599px) {
/* smartphone */
.graphic {
transform: rotate(90deg);
height: 100%;
display: block;
}
}
I expect the svg to not overflow from the green container (it must fit it's height).
The height of your svg doesnt not exceed the height of your container. Problem is you turn your svg 90 degrees so that visually it's width becomes it's height, but that's only visually, cos it's still counted as width.
EDIT:
Added a jQuery solution. With this setup if viewport is smaller than 600 your svg will be rotated as before but JavaScript will replace height value with width value and width value with height value. Here is the code:
$(window).resize(function() {
if ($(window).width() <= 600) {
var h = $('#svg').height();
var w = $('#svg').width();
$('#svg').attr('width', h);
$('#svg').attr('height', w);
}
});
.container {
background-color: green;
}
.graphic {
transform: scaleY(-1);
}
#media (max-width: 599px) {
/* smartphone */
.container {
height: 200px;
}
.graphic {
transform: rotate(90deg);
height: 100%;
display: block;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<svg viewBox="0 0 700 100" preserveAspectRatio="none" class="graphic" style="" id="svg">
<polyline fill="red" stroke="none" points="
0,0
0,15
100,14
200,18
300,21
400,23
500,22
600,17
700,17
700,0
0,0
" />
</svg>
</div>
Other choice would be placing 2 svgs (one vertically and one horizontally aligned) and displaying only one of them at a time.
For anyone interested, I've finally settled with using 2 inline svg :
HTML :
<div class="container">
<svg
viewBox="0 0 700 100"
preserveAspectRatio="none"
class="graphic landscape"
>
<!-- <g transform="translate(0,100)"></g><g transform="scale(1,-1)"></g> -->
<polyline
fill="lightgrey"
stroke="none"
points="
0,0
0,60
100,56
200,72
300,84
400,92
500,88
600,68
700,68
700,0
"
/>
</svg>
<svg
viewBox="0 0 100 700"
preserveAspectRatio="none"
class="graphic portrait"
>
<!-- <g transform=" translate(0,100) "></g><g transform="scale(1,-1) "></g> -->
<polyline
fill="lightgrey "
stroke="none "
points="
0,0
60,0
56,100
72,200
84,300
92,400
88,500
68,600
68,700
0,700
"
/>
</svg>
</div>
CSS :
.container {
background-color: green;
height: 50vh;
}
.graphic {
transform: scaleY(-1);
overflow-x: hidden;
overflow-y: hidden;
}
.landscape {
display: block;
width: 100%;
/* max-height: 100%; */
height: 100%;
}
.portrait {
display: none;
height: 100%;
/* max-width: 100%; */
width: 100%;
}
#media (max-width: 599px) {
/* smartphone */
.portrait {
display: block;
}
.landscape {
display: none;
}
}
Next step is using js to automate the coordinate of the second graph I guess
EDIT: You should actually use display: none; and display: block; here, since visibility: hidden; and visibility: visible; doesnt show the tag too but allocate space for it and we want to avoid that.
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.
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.
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.
I'm trying to figure out a way to center vertically my SVG Tag.
Basically, here is a simplified SVG code i'm trying to center :
<svg height="272" style="background-color:transparent;margin-left: auto; margin-right: auto;" width="130" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g style="font-size: 0.7em;" transform="scale(1 1) rotate(0) translate(0 270)">
<g id="1" style="font-size: 0.7em;">
<image height="32" width="32" x="49" xlink:href="../../images/JOB.GIF" y="-270"/>
</g>
</g>
</svg>
I have no trouble putting it in the middle (horizontally speaking) of the page, however i'd like it to be vertically centered as well.
I can add wrappers, but i'd like to know a generic way of doing this, not depending on the SVG size nor the window size.
I have tried multiple ways, but nothing worked.
Thanks,
I updated this answer as current browser have a lot better solution for that.
How wise man said, first year you learn html and css, for another few years you learn advanced javascript and after five years you finally learn how to vertically center div.
to vertically/horizontally align anything in css you can use two main ways:
Absolute
<div class="outside">
<div class="inside">Whatever</div>
</div>
and css:
.outside{
position:relative;
}
.inside{
position:absolute;
top:50%;
bottom:50%;
transform:translate(-50%, -50%);
}
the only issue with that is that element doesn't generate the height.
Flexbox
Flexbox has now pretty good support so why not to use it. https://caniuse.com/#feat=flexbox
Using flexbox your item doesn't need to be absolute so it will generate the height. code:
<div class="outside">
<div>Whatever</div>
</div>
and css:
.outside{
display: flex;
align-items: center;
justify-content: center;
}
Old answer:
you have height and width so u can use margin : auto auto;
or put it in div with
position:absolute ;
left:50% ;
margin-left: -(half of width of image)px;
top:50% ;
margin-top: -(half of height of image)px;
the second one will be better if u will be doing some stuff with it (javascript animation or something)
I didn't check it but maybe u can use second option for svg (without outer div) too
It's Simple!
HTML:
<div class="a">
<div class="b">
<div class="c">
<!-- Your SVG Here -->
</div>
</div>
</div>
CSS:
<style>
.a {
display: table;
position: absolute;
height: 100%;
width: 100%;
}
.b {
display: table-cell;
vertical-align: middle;
}
.c {
margin-left: auto;
margin-right: auto;
height: /* Your size in px, else it will expand to your screen size!*/
width: /* Your size in px, else it will expand to your screen size!*/
}
</style>
If you provide your svg element with a viewBox attribute and set it's width & height attributes to 100% then all should be well (in most browsers..)
$(document).ready(function(){
$(".panel-left").resizable({handleSelector: ".splitter",containment: "parent"});
});
#ctr
{
position: absolute;
border: 1px solid #131313;
top: 5%;
left: 5%;
bottom: 5%;
right: 5%;
display: flex;
flex-direction: row;
}
#ctr svg
{
height: 100%;
width: 100%;
}
.panel-left
{
flex: 0 0 auto;
padding: 10px;
width: 50px;
min-height: 50px;
min-width: 50px;
max-width: 80%;
max-height: 100%;
white-space: nowrap;
background: #131313;
color: white;
}
.splitter
{
flex: 0 0 auto;
width: 18px;
}
.panel-right
{
flex: 1 1 auto;
padding: 10px;
min-width: 20px;
background: #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<div style="visibility:hidden; position:absolute; width:0">
<svg>
<g id="my-funky-svg-defs">
<defs>
<radialGradient id="gradient" cx="25%" cy="25%" r="100%" fx="40%" fy="40%">
<stop offset= "0%" stop-color="hsla(313, 80%, 80%, 1)"/>
<stop offset= "40%" stop-color="hsla(313, 100%, 65%, 1)"/>
<stop offset="110%" stop-color="hsla(313, 100%, 50%, 0.7)"/>
</radialGradient>
</defs>
<title>smarteee</title>
<circle class="face" cx="200" cy="200" r="195" fill="url(#gradient)" />
<ellipse class="eye eye-left" cx="140" cy="150" rx="10" ry="40" fill="#131313"/>
<ellipse class="eye eye-right" cx="260" cy="150" rx="10" ry="40" fill="#131313"/>
<path class="smile" d="M120,280 Q200,330 280,280" stroke-width="10" stroke="#131313" fill="none" stroke-linecap="round"/>
</g>
</svg>
</div>
<div id=ctr>
<div class="panel-left">
<svg viewBox="0 0 400 400"><use xlink:href="#my-funky-svg-defs"></use></svg>
</div>
<div class="splitter">
</div>
<div class="panel-right">
<svg viewBox="0 0 400 400"><use xlink:href="#my-funky-svg-defs"></use></svg>
</div>
</div>
&here's a corresponding jsfiddle to play with
NB: there is also the preserveAspectRatio attribute that works in conjunction with the viewBox settings. eg: preserveAspectRatio="xMidYMid meet"
You could try using flexbox.
Simple HTML:
<div class="outside">
<svg />
</div>
CSS:
.outside {
display: flex;
align-items: center; /* vertical alignment */
justify-content: center; /* horizontal alignment */
}
HTML with your sample:
<div class="outside">
<svg height="272" style="background-color:transparent;margin-left: auto; margin-right: auto;" width="130" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g style="font-size: 0.7em;" transform="scale(1 1) rotate(0) translate(0 270)">
<g id="1" style="font-size: 0.7em;">
<image height="32" width="32" x="49" xlink:href="../../images/JOB.GIF" y="-270"/>
</g>
</g>
</svg>
</div>
Flexbox browser support: caniuse flexbox
Learn about Flexbox: CSS Tricks Guide to Flexbox
Learn by playing: Flexbox Froggy
I've finally used some JS code to do so.
I was using the solution from here : Best way to center a <div> on a page vertically and horizontally?
Which is :
div {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top:0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
But the problem is that if the SVG is bigger than the window size, it gets cropped.
Here is the JS code i've used in onLoad :
var heightDiff = window.innerHeight - svg.height.baseVal.value;
var widthDiff = window.innerWidth - svg.width.baseVal.value;
if (heightDiff > 0)
svg.style.marginTop = svg.style.marginBottom = heightDiff / 2;
if (widthDiff > 0)
svg.style.marginLeft = svg.style.marginRight = widthDiff / 2;