0

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?

Community
  • 1
  • 1
Rocky
  • 5
  • 3
  • Looked like there was a newline artifact showing up in your jsfiddle CSS syntax. I removed it and forked this one... http://jsfiddle.net/1ffrazka/... try it out. – Lowkase Aug 19 '14 at 05:13
  • What zero-width spaces? How do you see a zero-width thing? Describe what you see as the actual problem, instead of inventing names for it, and reduce the issue to a smaller case, e.g. remove all CSS that is not essential to producing the issue. And add relevant HTML. – Jukka K. Korpela Aug 19 '14 at 05:18
  • Totally see what you mean (I see a little red circle in FF, btw). But this seems to be a problem with your text editor rather than CSS, can you try re-installing a fresh copy? Maybe using some faulty plugin? Also, I have found people from Sweden complaining at SublimeText forum about this same behavior, is that your case? – Devin Aug 19 '14 at 05:24
  • @Jukka, you see it as a little red circle in both the jsfiddle and on Chrome Developer tools. I also don't believe it's an invented name, considering that I just spent a fair amount of time looking into them, but I'm open to being corrected. The relevant html is only an empty div and is easily evident on the fiddle. I apologize if the question wasn't detailed enough. – Rocky Aug 19 '14 at 05:29
  • @Lowkase, thanks, yeah I was able to spot the artifact as well and remove it on the fiddle, but wasn't able to get it removed in the code and it was consistently there when I ran the code or copied and pasted into, well, anywhere. – Rocky Aug 19 '14 at 05:31
  • @Fabio, that was my among my first thoughts, did a fresh install, checked through the settings, disabled most of my plugins, no difference. The solution I reference in the question is here: http://stackoverflow.com/questions/20356784/delete-u200b-zero-width-space-characters-using-sublime-text-3, but that seems like a poor workaround – Rocky Aug 19 '14 at 05:33
  • @Fabio, missed the forum part of your comment, not finding what you're referencing when I search their forums, maybe you could point me in the right direction? – Rocky Aug 19 '14 at 05:42
  • sure, see https://www.sublimetext.com/forum/viewtopic.php?f=3&t=9607 , but there are no answers to this either. However, they seem to be describing your exact issue and maybe some day someone will answer – Devin Aug 19 '14 at 05:44
  • Yeah, looks like it may be the same issue, thanks for that. Very odd, and to make it more interesting, it also looks like Notepad++ is doing the same thing when I rewrite it in there, which basically leaves me as confused I was before, wonderful. – Rocky Aug 19 '14 at 05:54
  • @Rocky I wrote the answer in the question you linked, and I've just updated it to add an asynchronous ST3-specific version. Since the plugin running the `U+200B` search is now in a different thread, it shouldn't affect your typing speed or the performance of the main thread at all. Give it a try, and let me know what you think. Just FYI, there are already a few built-in plugins (and more if you've installed a bunch of packages) running event listeners, so one more shouldn't drastically change things. I haven't done any performance testing, but my revised plugin shouldn't change things much. – MattDMo Aug 21 '14 at 18:59
  • @Matt, that is fantastic, it works perfectly for me, and I don't notice any performance issues at all(referring to the ST3 version). A big thank you. I can't upvote the other answer or much else because of my lacking reputation, but if you want to answer here, I can mark it as correct. Thanks! – Rocky Aug 24 '14 at 06:11
  • @Rocky I added the answer below. Please note that I changed the code slightly so that `U+200B` is now highlighted in the more visible `invalid` scope, instead of `string`, so any instances are much easier to see. – MattDMo Aug 24 '14 at 19:10

1 Answers1

1

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.

MattDMo
  • 100,794
  • 21
  • 241
  • 231