Rocky
Rocky

Reputation: 5

Zero-width space affecting styling

Just spent a piss-me-off amount of time running down this bug and am hoping someone has an answer as to what's causing it so I can hopefully never deal with it again.

I'm writing raw CSS for a site I'm building and am using psuedo-elements to add upward and downward pointing chevrons to the top and bottom, respectively, of some of the pages.

#chevronUp {
  position: fixed;
  left:50%;
  top:5%;
  text-align: center;
  padding: 0px;
  margin-bottom: 0px;
  height: 8px;
  width: 100px;
}
#chevronDown {
  position: fixed;
  left:50%;
  bottom:5%;
  text-align: center;
  padding: 0px;
  margin-bottom: 0px;
  height: 8px;
  width: 100px;
  z-index:10;
}

#chevronUp:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 51%;
  background: #3c3f44;
  -webkit-transform: skew(0deg, -35deg);
  -moz-transform: skew(0deg, -35deg);
  -ms-transform: skew(0deg, -35deg);
  -o-transform: skew(0deg, -35deg);
  transform: skew(0deg, -35deg);
}

#chevronDown:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 51%;
  background: #3c3f44;
  -webkit-transform: skew(0deg, 35deg);
  -moz-transform: skew(0deg, 35deg);
  -ms-transform: skew(0deg, 35deg);
  -o-transform: skew(0deg, 35deg);
  transform: skew(0deg, 35deg);
}

#chevronUp:after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 50%;
  background: #3c3f44;
  -webkit-transform: skew(0deg, 35deg);
  -moz-transform: skew(0deg, 35deg);
  -ms-transform: skew(0deg, 35deg);
  -o-transform: skew(0deg, 35deg);
  transform: skew(0deg, 35deg);
  }​

#chevronDown:after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 50%;
  background: #3c3f44;
  -webkit-transform: skew(0deg, -35deg);
  -moz-transform: skew(0deg, -35deg);
  -ms-transform: skew(0deg, -35deg);
  -o-transform: skew(0deg, -35deg);
  transform: skew(0deg, -35deg);
}

I thought this would be relatively simple, but I kept ending up with the downward facing chevron missing the right half, like so:

http://jsfiddle.net/h3yqhhxc/1/

You can see it on the jsfiddle, there's a pesky little zero-width space character hanging out after closing bracket on the #chevronUp:after selector (on the #chevronDown:after closing bracket too).

Turns out these things are tough to delete.

I'm using Sublime Text 2 and found a script here on SO which worked, but I have no desire to have my text editor running an extra plugin after every keystroke.

So I tried some hacky behavior and ended up with this, which works, I'm assuming, by removing the zero-width space from affecting the selector following it:

#chevronUp:after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 50%;
  background: #3c3f44;
  -webkit-transform: skew(0deg, 35deg);
  -moz-transform: skew(0deg, 35deg);
  -ms-transform: skew(0deg, 35deg);
  -o-transform: skew(0deg, 35deg);
  transform: skew(0deg, 35deg);
  }​{}   <------Note the extra brackets

http://jsfiddle.net/yfm9c5fz/

But there's got to be a better answer than that? Where are these zero-width spaces being added/how do I stop it?

Upvotes: 0

Views: 2228

Answers (1)

MattDMo
MattDMo

Reputation: 102892

Here is a Sublime Text 3-specific plugin that runs asynchronously, looking for instances of zero-width spaces (Unicode code point \u200b). Every time the current view is modified, it searches through it character by character looking for the zero-width space character. If it finds one, it adds the location to a list and keeps looking until it reaches the end of the file. Then, if any characters were found, they are highlighted according to the invalid scope in your theme. Once highlighted, they can be selected and deleted. Since it runs asynchronously, you shouldn't see any performance drop while editing.

Open a new file in Sublime, and set its syntax to Python. Paste the following into it:

import sublime_plugin

class ShowZeroWidthSpace(sublime_plugin.EventListener):
    def on_modified_async(self, view):
        spaces = []
        p = 0
        while True:
            s = view.find('\u200b', p + 1)
            if not s:
                break
            spaces.append(s)
            p = s.a

        if spaces:
            view.add_regions("zero-width", spaces, "invalid")
        else:
            view.erase_regions("zero-width")

Save the file in your Packages/User directory as show_zero_width_space.py, and it should start working immediately. You can find your Packages directory by selecting the Preferences -> Browse Packages... menu option.


Once you've determined that your file contains U+200B characters, you can easily get rid of them by using regex find and replace. Select Find -> Replace..., and in the "Find What" field enter \x{200b}. Leave the "Replace With" field blank, then select the .* Regular Expression button, the Wrap button, and the Highlight Matches button:

U+200B

Hit Replace All and you're all set.

Upvotes: 1

Related Questions