128

I would like to use dynamic text as background of certain elements in my tag. Because of this, I can use images (dynamic text). How do I do it with just CSS or JavaScript?

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
chustar
  • 12,225
  • 24
  • 81
  • 119

11 Answers11

185

SVG text background image

body {
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='50px' width='120px'><text x='0' y='15' fill='red' font-size='20'>I love SVG!</text></svg>");
}
<p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p>
<p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p><p>I hate SVG!</p>

Here is an indented version of the CSS so you can understand better. Note that this does not work, you need to use the single liner SVG from the snippet above instead:

body {
  background-image:url("data:image/svg+xml;utf8,
  <svg xmlns='http://www.w3.org/2000/svg' version='1.1'
       height='50px' width='120px'>
    <text x='0' y='15' fill='red' font-size='20'>I love SVG!</text>
  </svg>");
}

Not sure how portable this is (works on Firefox 31 and Chrome 36), and it is technically an image... but the source is inline and plain text, and it scales infinitely.

@senectus found that it works better on IE if you base64 encode it: https://stackoverflow.com/a/25593531/895245

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
94

You can have an absolutely positioned element inside of your relative positioned element:

#container {
   position: relative;
}

#background {
   position: absolute;
   top: 0;
   left: 0;
   bottom: 0;
   right: 0;
   z-index: -1;
   overflow: hidden;
}
<div id="container">
    <div id="background">
    Text to have as background
    </div>
    Normal contents
</div>

Here's an example of it.

Sarfaraaz
  • 488
  • 6
  • 17
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
58

It may be possible (but very hackish) with only CSS using the :before or :after pseudo elements:

.bgtext {
  position: relative;
}

.bgtext:after {
  content: "Background text";
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
}
<div class="bgtext">
  Foreground text
</div>

This seems to work, but you'll probably need to tweak it a little. Also note it won't work in IE6 because it doesn't support :after.

j08691
  • 204,283
  • 31
  • 260
  • 272
DisgruntledGoat
  • 70,219
  • 68
  • 205
  • 290
  • Update: As for now, all modern browsers support pseudo elements. For instance that is how FontAwesome works for CSS icons (using :before on inline elements). – Cédric Françoys Jun 14 '16 at 13:26
  • Just be aware that Firefox doesn't allow :before and :after on elements that cannot have inner content, like input fields. This respects the official CSS spec. – nicbou Sep 20 '20 at 11:21
22

Ciro's solution about an SVG Data URI background containing the text is very clever.

However, it won't work in IE if you just add the plain SVG source to the data URI.

In order to get around this and make it work in IE9 and up, encode the SVG to base64. This is a great tool.

So this:

background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"><text x="5%" y="5%" font-size="30" fill="red">I love SVG!</text></svg>');

Becomes this:

background:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjx0ZXh0IHg9IjUlIiB5PSI1JSIgZm9udC1zaXplPSIzMCIgZmlsbD0icmVkIj5JIGxvdmUgU1ZHITwvdGV4dD48L3N2Zz4=');

Tested and it works in IE9-10-11, WebKit (Chrome 37, Opera 23) and Gecko (Firefox 31).

http://jsfiddle.net/qapp5dLn/

senectus
  • 409
  • 4
  • 14
  • 1
    This is a better tool: https://jpillora.com/base64-encoder/ simpile, no errors, autofilling, image previewing. Yep, it is better in leaps and bounds. – Jack G Apr 18 '17 at 02:45
11

@Ciro

You can break the inline svg code with back-slash "\"

Tested with the code below in Chrome 54 and Firefox 50

body {
    background: transparent;
    background-attachment:fixed;
    background-image: url(
    "data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='170px' height='50px'> \
    <rect x='0' y='0' width='170' height='50' style='stroke:white; fill:gray; stroke-opacity: 0.3; stroke-width: 3px; fill-opacity: 0.7; stroke-dasharray: 10 5; stroke-linecap=round; '/> \
    <text x='85' y='30' style='fill:lightBlue; text-anchor: middle' font-size='16' transform='rotate(10,85,25)'>I love SVG!</text></svg>");
}

I even Tested this,

background-image: url("\
data:image/svg+xml;utf8, \
  <svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='170px' height='50px'> \
    <rect x='0' y='0' width='170' height='50'\
      style='stroke:white; stroke-width: 3px; stroke-opacity: 0.3; \
             stroke-dasharray: 10 5; stroke-linecap=round; \
             fill:gray;  fill-opacity: 0.7; '/> \
    <text x='85' y='30' \
      style='fill:lightBlue; text-anchor: middle' font-size='16' \
      transform='rotate(10,85,25)'> \
      I love SVG! \
    </text> \
  </svg>\
");

and it works (at least in Chrome 54 & Firefox 50 ==> usage in NWjs & Electron guarenteed)

Athmailer
  • 129
  • 1
  • 4
11

Using pure CSS:

(But use this in rare occasions, because HTML method is PREFERRED WAY).

.container{
 position:relative;
}
.container::before{ 
 content:"";
 width: 100%; height: 100%; position: absolute; background: black; opacity: 0.3; z-index: 1;  top: 0;   left: 0;
 background: black;
}
.container::after{ 
 content: "Your Text"; position: absolute; top: 0; left: 0; bottom: 0; right: 0; z-index: 3; overflow: hidden; font-size: 2em; color: red;    text-align: center; text-shadow: 0px 0px 5px black; background: #0a0a0a8c; padding: 5px;
 animation-name: blinking;
 animation-duration: 1s;
 animation-iteration-count: infinite;
 animation-direction: alternate;
}
@keyframes blinking {
 0% {opacity: 0;}
 100% {opacity: 1;}
}
<div class="container">here is main content, text , <br/> images and other page details</div>
T.Todua
  • 53,146
  • 19
  • 236
  • 237
6

I hope this might help you

<!DOCTYPE html>
<html>
<head>
<style>

 :root:after { 
         
            content: "Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark   Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark Watermark "; 
            position: fixed; 
            transform: rotate(300deg); 
            -webkit-transform: rotate(300deg); 
            color: rgb(187, 182, 182); 
            top:0;                     
            z-index: -1; 
        } 
</style>
</head>
<body>
<p>hey my name is JHM</p>
</body>
</html>
JHM16
  • 649
  • 8
  • 12
2

You could make the element containing the bg text have a lower stacking order ( z-index, position ) and possibly even set opacity. So the element you need on top would need a higher stacking order ( z-index:5; position:relative; for ex ) and the element behind would need something lower ( default or just a lower z-index like 3 and position:relative; ).

meder omuraliev
  • 183,342
  • 71
  • 393
  • 434
1

A simple solution:

    background-text{
        font-size:30px;
        font-weight:900;
        color:#f1f1f1;
        position:absolute;
        z-index:-1;
    }
<div id="container">
<background-text> This is background</background-text>
This if foreground text
</div>

You do not really need to set "position:relative" for the container, except you need to setup relative position for background.

Piotr
  • 85
  • 1
  • 2
1

Ran across this post looking for an idea how to add text to the background of a div container and this was my solution I came up with using two flex containers.

.foreground {
  display: flex;
  background-color: #f7fcfc;
  justify-content: center;
  align-content: center;
  border-radius: 3px;
  border: 2px solid #86cdb6;
  margin: 1em;
  width: 100px;
  height: 100px;
}

.foreground p {
  font-family: sans-serif;
  font-size: 12px;
  font-weight: 900;
  color: #86cdb6;
  margin: auto;
  text-align: center;
  z-index: 2;
}

.background {
  position: absolute;
  display: flex;
  align-content: center;
  justify-content: center;
  width: inherit;
  height: inherit;
  z-index: 1;
  overflow: hidden;
}

.background p {
  font-family: sans-serif;
  font-size: 22px;
  font-weight: 400;
  color: #ddf1ef;
  text-align: center;
  margin: auto;
}
<div class="foreground">
  <div class="background">
    <p>Background
      <br> Background
      <br> Background
      <br> Background
    </p>
  </div>
  <p>Foreground</p>
</div>
0

I have used this code.

   const StepIcon = ({ label, description }) => (
    <div>
        <span className='step-icon' style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            <CircleOutlinedIcon />
            <div style={{ position: 'absolute', fontSize: 10 }}>{label}</div>
        </span>
        <div>{description}</div>
    </div>
);

            <Stepper activeStep={0} alternativeLabel>
                {stepperSteps.map((label, index) => (
                    <Step key={label}
                        sx={{
                            '& .MuiStepLabel-root .MuiSvgIcon-root': {
                                color: theme.palette.primary.main, // circle color (ACTIVE)
                                borderWidth: 1
                            }
                        }}
                    >
                        <StepButton icon={<StepIcon label={index + 1} description={label} />} />
                    </Step>
                ))}
            </Stepper>
sandeep.gosavi
  • 610
  • 2
  • 10
  • 27