CSS redaction effect
Ok, maybe you’re writing internet creepypasta or something and you want redacted text.
Here are some things to consider:
- Do you need a text-shadow?
- Are you picking a specific font, or are you using a system font?
- Do you want the redacted text to be meaningless, or do you want easter-egg text which can be read by highlighting it, viewing source, cut-pasting?
U+2588 FULL BLOCK
Place runs of this character: █. Pepper <wbr> between every few characters to make the redacted text line-wrap more realistically.
On some fonts, and on some user-agents, this ends up with small hairline cracks between the block characters. Wrapping runs of redacted text in a span with a small negative letter-spacing may help, although it will slightly throw off the rhythm of monospace text.
Sadly, a text-shadow reveals the wbrs.
███<wbr>██████<wbr>███████<wbr>███<wbr>██████- Kinda works with text-shadow.
- Works with all fonts.
- No underlying text.
Background color
The obvious CSS-based solution is a background-color, and it works, but depending on the font and line-height it can leave too much space for the font’s ascenders and descenders and look too thick.
This demo looks fine with my Android system fonts, but looks terrible with Noto Sans, my computer’s system font.
- Does not work with text-shadow.
- Works with all fonts, although some fonts have poor sizing.
- Has underlying text.
Gradient background
You can tweak the percentages to adjust the size and position of the redaction stripe. It’s relative to the background-color rectangle.
This looks ok with Noto Sans, but on my phone the background-color method is already small enough, so shrinking it further with this method makes it look too skinny.
color: transparent;
background: linear-gradient(0deg, transparent 15%, black 15% 85%, transparent 85%);- Does not work with text-shadow.
- Works with all fonts, although some fonts have poor sizing.
- Has underlying text.
Wide strikethrough
You can use a text-decoration: line-through stripe, with the stripe’s width cranked up using text-decoration-thickness.
Unlike the other methods, this works with text-shadow; the whole redaction stripe gets a shadow.
color: transparent;
text-decoration: line-through;
text-decoration-thickness: 110%;- Works with text-shadow.
- Works with all fonts, although different fonts may require a different text-decoration-thickness.
- Has underlying text, but the redaction remains visible when it’s highlighted (needs to be cut-and-pasted outside the document).
Things that don’t work very well
Repositioned underline
One problem with line-through is that you can’t move it up and down if you don’t like its position (on many of the fonts I’ve looked at, I feel it’s a tiny bit too low.)
Underlines can be moved, though, with text-underline-offset.
Problems:
- Of course you have to offset the underline way up to cover the text. But different user-agents seem to position the underline differently, even if the same font is used.
- Firefox paints the underline’s
text-shadowon top of the text’s. Google Chrome paints them in the other order, sotext-shadowdoesn’t work.
color: transparent;
text-decoration: underline;
text-decoration-thickness: 110%;
text-underline-offset: -0.9em; /* magic number */
text-decoration-skip-ink: none;
text-decoration-color: black;- Doesn’t reliably work with text-shadow (works on Firefox, but not Chrome)
- Works with all fonts, but requires even more eyeballing.
- Has underlying text. Revealed when highlit on Firefox, remains crossed-out on Chrome.
inline-block
I wasn’t able to get anything involving display: inline-block to work well. It interacts terribly with text wrapping:
- Redacted text won’t wrap at all, even with
overflow-wrapandword-break. - Periods after redacted text can wrap onto a line all by themselves.
display: inline-block;
background: black;
color: transparent;
height: 0.9em;
transform: translateY(0.25em);- Just bad.