301

Is it possible to use CSS/CSS3 to mirror text?

Specifically, I have this scissors char “✂” (✂) that I'd like to display pointing left and not right.

Kunj
  • 1,980
  • 2
  • 22
  • 34
pistacchio
  • 56,889
  • 107
  • 278
  • 420
  • 10
    If the scissors image for some reason doesn't work out for you, I've seen it faked with %< and >% – Pete Wilson Mar 23 '11 at 14:23
  • 1
    See this thread: http://stackoverflow.com/questions/3433641/flipping-inverting-mirroring-text-using-css-only [1]: http://stackoverflow.com/questions/3433641/flipping-inverting-mirroring-text-using-css-only – Lucas Vall Jul 24 '13 at 08:37
  • 3
    The answer by Micheal is more accurate. Can you please update the correct answer? Because the answer which you've marked as correct is not mirror but rotation by 180 degrees. – Sanket Sahu Dec 18 '13 at 14:47
  • @PeteWilson, ? Is the ✂ char so common? What's it used for? – Pacerier Jun 30 '15 at 07:16
  • +5 for nice question – Elyor Sep 22 '15 at 11:44
  • 4
    Be aware that the rotation is different depending on the emoji implementation. On Apples emoji set it’s pointing down. – Akkumulator Dec 29 '17 at 09:56

15 Answers15

524

You can use CSS transformations to achieve this. A horizontal flip would involve scaling the div like this:

-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);

And a vertical flip would involve scaling the div like this:

-moz-transform: scale(1, -1);
-webkit-transform: scale(1, -1);
-o-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);

DEMO:

span{ display: inline-block; margin:1em; } 
.flip_H{ transform: scale(-1, 1); color:red; }
.flip_V{ transform: scale(1, -1); color:green; }
<span class='flip_H'>Demo text &#9986;</span>
<span class='flip_V'>Demo text &#9986;</span>
Hernán Eche
  • 6,529
  • 12
  • 51
  • 76
methodofaction
  • 70,885
  • 21
  • 151
  • 164
  • 1
    It is certainly the nost standards compliant answer, unfortunately we don't live in a world where this actually works for all use cases yet. – Chris Sobolewski Oct 20 '13 at 02:10
  • Could you include the actual browser prefixes in your answer, with the non-prefixed last? The CSS as you gave it does not work. – Serrano Jan 30 '14 at 15:21
  • @SerranoPereira indeed, thanks for the suggestion. Answer amended. – methodofaction Jan 31 '14 at 21:51
  • This should be the correct answer as it is a real mirror. The chosen answer is only a rotate which in the case of asymmetrical anything will not provide a mirror image. – gregtzar Feb 13 '14 at 00:57
  • Possible side-note: Also mirrors padding (`padding-right: 10px;` will show 10px padding on the left), but not margin. – Marcel Mar 13 '14 at 15:57
  • 14
    Note that [CSS transform doesn't work on inline elements](http://stackoverflow.com/questions/14883250/css-transform-doesnt-work-on-inline-elements) like Foundation's suggested tags, unless you also give then display: inline-block. – enigment Nov 16 '16 at 01:54
71
-moz-transform: scale(-1, 1);
-webkit-transform: scale(-1, 1);
-o-transform: scale(-1, 1);
-ms-transform: scale(-1, 1);
transform: scale(-1, 1);

The two parameters are X axis, and Y axis, -1 will be a mirror, but you can scale to any size you like to suit your needs. Upside down and backwards would be (-1, -1).

If you're interested in the best option available for cross browser support back in 2011, see my older answer.

Community
  • 1
  • 1
Chris Sobolewski
  • 12,819
  • 12
  • 63
  • 96
  • 22
    Technically this is not a mirror. its rotated. So it'll only work with some type of elements – borisrorsvort Jan 16 '13 at 16:28
  • 6
    I had some issues in Chrome until I added display: inline-block to my span (using pictos fonts) – Clarence Liu Mar 26 '13 at 21:13
  • 1
    Given that when this question was asked, browser transforms were not widely supported, I would argue that this WAS the right answer. In fact transforms are not supported until IE 9, so I would argue that this is STILL the right answer, for at least a little while longer. – Chris Sobolewski Nov 02 '13 at 21:59
  • This answer is wrong, it is not a mirror. It only works in this one case because the symbol given in the example is vertically asymmetrical. – gregtzar Feb 13 '14 at 00:58
  • Although this is useful in itself, it's not the answer to the exact question asked. I found this question through a search engine because I wanted to flip an image horizontally. It's not symmetrical like the OPs scissors. – gillytech Aug 25 '14 at 03:00
  • previous comments are no longer relevant since the answer now correctly suggests the use of `scale` and not `rotate(-180deg)` – keeri Aug 24 '20 at 14:52
68

Real mirror:

.mirror{
    display: inline-block; 
    font-size: 30px;

    -webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
    -moz-transform: matrix(-1, 0, 0, 1, 0, 0);
    -o-transform: matrix(-1, 0, 0, 1, 0, 0);
    transform: matrix(-1, 0, 0, 1, 0, 0);
}
<span class='mirror'>Mirror Text<span>
vsync
  • 118,978
  • 58
  • 307
  • 400
  • 17
    You should *always* put the standards-compliant (non-prefixed) property last, so that when the standard is adopted by a browser, it will use the standards-based version instead of the (older, buggier) prefixed version. In this case, that means "transform: matrix(-1, 0, 0, 1, 0, 0);" should be the *last* property. (Edited the answer to reflect this.) – Jay Dansand Oct 02 '13 at 16:47
  • 7
    I don't know whether this should be on the correct answer or the question but I want to let fontawesome / bootstrap users know about the `fa-flip-horizontal` and `fa-flip-vertical` properties – lol Jan 05 '14 at 11:25
  • 2
    Great real answer. However display:block; not necessarily needed. – Gilly Jan 08 '14 at 07:59
  • 6
    yep... display:block; or inline-block is needed – dGo May 04 '15 at 21:10
  • This was really helpful to keep the correct text orientation of an element's backface when rotated along the Y axis. For ex: ```backface-visibility: visible; transform-origin: center center; transform-style: preserve-3d; transform: matrix(-1, 0, 0, 1, 0, 0) rotateY(180deg) ;``` – parliament Mar 24 '18 at 15:11
16

You can user either

.your-class{ 
      position:absolute; 
      -moz-transform: scaleX(-1); 
      -o-transform: scaleX(-1); 
      -webkit-transform: scaleX(-1); 
      transform: scaleX(-1); 
      filter: FlipH;  
}

or

 .your-class{ 
  position:absolute;
  transform: rotate(360deg) scaleX(-1);
}

Notice that setting position to absolute is very important! If you won't set it, you will need to set display: inline-block;

Emanuela Colta
  • 2,129
  • 4
  • 18
  • 31
8

I cobbled together this solution by scouring the Internet including

This solution seems to work in all browsers including IE6+, using scale(-1,1) (a proper mirror) and appropriate filter/-ms-filter properties when necessary (IE6-8):

/* Cross-browser mirroring of content. Note that CSS pre-processors
  like Less cough on the media hack. 

  Microsoft recommends using BasicImage as a more efficent/faster form of
  mirroring, instead of FlipH or some kind of Matrix scaling/transform.
  @see http://msdn.microsoft.com/en-us/library/ms532972%28v=vs.85%29.aspx
  @see http://msdn.microsoft.com/en-us/library/ms532992%28v=vs.85%29.aspx
*/

/* IE8 only via hack: necessary because IE9+ will also interpret -ms-filter,
  and mirroring something that's already mirrored results in no net change! */
@media \0screen {
  .mirror {
    -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(mirror=1)";
  }
}
.mirror {
  /* IE6 and 7 via hack */
  *filter: progid:DXImageTransform.Microsoft.BasicImage(mirror=1);
  /* Standards browsers, including IE9+ */
  -moz-transform: scale(-1,1);
  -ms-transform: scale(-1,1);
  -o-transform: scale(-1,1); /* Op 11.5 only */
  -webkit-transform: scale(-1,1);
  transform: scale(-1,1);
}
Jay Dansand
  • 789
  • 1
  • 9
  • 13
6

There's also the rotateY for a real mirror one:

transform: rotateY(180deg);

Which, perhaps, is even more clear and understandable.

EDIT: Doesn't seem to work on Opera though… sadly. But it works fine on Firefox. I guess it might required to implicitly say that we are doing some kind of translate3d perhaps? Or something like that.

jeromej
  • 10,508
  • 2
  • 43
  • 62
  • 1
    For those wondering this is a 3D transform. I think it is definitely more readable/understandable than the scale and matrix methods given previously. – gregtzar Feb 13 '14 at 01:02
  • I do not see how a rotation is a mirror - that would only appear to be so in one special case. – cel sharp Apr 16 '20 at 07:47
  • @celsharp it's on the Y axis, so you see the image/element from its back, thus, mirrored. – jeromej Apr 16 '20 at 08:20
6

For cross browser compatibility create this class

.mirror-icon:before {
    -webkit-transform: scale(-1, 1);
    -moz-transform: scale(-1, 1);
    -ms-transform: scale(-1, 1);
    -o-transform: scale(-1, 1);
    transform: scale(-1, 1);
}

And add it to your icon class, i.e.

<i class="icon-search mirror-icon"></i>

to get a search icon with the handle on the left

Michael
  • 357
  • 5
  • 11
3

Just adding a working demo for horizontal and vertical mirror flip.

.horizontal-flip {
  -moz-transform: scale(-1, 1);
  -webkit-transform: scale(-1, 1);
  -o-transform: scale(-1, 1);
  -ms-transform: scale(-1, 1);
  transform: scale(-1, 1);
}

.vertical-flip {
  -moz-transform: scale(1, -1);
  -webkit-transform: scale(1, -1);
  -o-transform: scale(1, -1);
  -ms-transform: scale(1, -1);
  transform: scale(1, -1);
}
<div class="horizontal-flip">
  Hello, World
  <input type="text">
</div>
<hr>
<div class="vertical-flip">
  Hello, World
  <input type="text">
</div>
niyasc
  • 4,440
  • 1
  • 23
  • 50
3

you can use 'transform' to achieve this. http://jsfiddle.net/aRcQ8/

css:

-moz-transform: rotate(-180deg);
-webkit-transform: rotate(-180deg);
transform: rotate(-180deg);
Rito
  • 5,117
  • 3
  • 40
  • 37
  • I believe this is technically not mirrored (except for some cases only, eg a shape with central symmetry). – jeromej Nov 17 '20 at 08:14
3

That works fine with font icons like 's7 stroke icons' and 'font-awesome':

.mirror {
  display: inline-block;
  transform: scaleX(-1);
}

And then on target element:

<button>
  <span class="s7-back mirror"></span>
  <span>Next</span>
</button>
Dmitry Anch
  • 424
  • 3
  • 4
2

Just one more example how the character could be flipped. Add vendor prefixes if you need ones but for now all modern browsers support unprefixed transform property. The only exception is Opera if Opera Mini mode is enabled (~3% world users).

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Text rotation</title>
  <style type="text/css" media="screen">
    .scissors {
      display: inline-block;
      font-size: 50px;
      color: red;
    }
    .original {
      color: initial;
    }
    .flipped {
      transform: rotateZ(180deg);
    }
    .upward {
      transform: rotateZ(-90deg);
    }
    .downward {
      transform: rotateZ(90deg);
    }
  </style>
  
</head>
<body>
  <ul>
    <li>Original: <span class="scissors original">&#9986;</span></li>
    <li>Flipped: <span class="scissors flipped">&#9986;</span></li>
    <li>Upward: <span class="scissors upward">&#9986;</span></li>
    <li>Downward: <span class="scissors downward">&#9986;</span></li>
  </ul>
</body>
</html>
drugan
  • 789
  • 9
  • 10
1

We can make pretty cool text effects using very little code, with css keyframes, and its alternate property (try removing alternate to see the difference):

span {
  font-weight: 1000; font-size: 3.3em;
}
small {
  display: inline-block;
  font-size: 2.3em;
  animation: 1s infinite alternate coolrotate
}

@keyframes coolrotate {
  from {
    transform: scale(1, 1) translate(-0.1em, 0)
  }
  to {
    transform: scale(-1, 1) translate(0, 0)
  }
}
<span>
  <span>c</span>
  <small>o</small>
  <span>o</span>
  <small>L</small>
  <small>...</small>
</span>
NVRM
  • 11,480
  • 1
  • 88
  • 87
0

You could try box-reflect

box-reflect: 20px right;

see CSS property box-reflect compatibility? for more details

Community
  • 1
  • 1
Sudeep
  • 19
0

this is what worked for me for <span class="navigation-pipe">&gt;</span>

display:inline-block;
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=4);

just need display:inline-block or block to rotate. So basically first answer is good. But -180 didn't worked.

Iggy
  • 2,014
  • 25
  • 21
-1

direction: rtl; is probably what you are looking for.

M--
  • 25,431
  • 8
  • 61
  • 93