2

I am making a source code display which supports line folding. While it's easy enough with CSS to ensure that the replacement text ("N lines hidden") is not selectable, I would like the hidden source code to still be selected, so the user can just select a chunk of code and not worry about whether part of it is missing due to a fold. Is there a (not-too-hacky) way to do this?

Mat
  • 202,337
  • 40
  • 393
  • 406
larsrc
  • 118
  • 2
  • 7

2 Answers2

6

Elements with opacity: 0 can be selected, although they're invisible.

.hidden-selectable {
    display: inline-block;
    width: 1px;
    opacity: 0;
}

<div>Visible<span class='hidden-selectable'>selectable</span></div>

In the above snippet, the 'selectable' string will be present in the selection and the copy-pasted text when the elements around it are selected.

The element needs to have a non-zero width and height, otherwise it doesn't appear in the selection. Also, it has to be inside the element flow (i.e. it can't have position: absolute), otherwise, again, it's not going to appear in the selection. Therefore I give it some very small but non-zero width, so that it doesn't affect flow visibly, but is still "visible enough" to be selectable.

Here's the fiddle.

Here's what else I've tried that doesn't work:

  • display: none
  • visibility: hidden
Stefan Dragnev
  • 14,143
  • 6
  • 48
  • 52
  • Just tried again in Chrome 86 and doesn't work for me. I see `Visible` and when selecting this word and what's around it, I don't see the word `selectable` appearing. Even with a Ctrl+A to select everything. Am I doing something wrong? – SaeX Oct 15 '20 at 12:21
  • You're not supposed to see it. It is selectable without ever becoming visible. That's what OP wanted. – Stefan Dragnev Oct 19 '20 at 14:22
  • Thanks for clarifying; I was looking for hidden-but-selectable text. – SaeX Oct 20 '20 at 19:05
2

If you have the following structure:

<html>
  <body>
    <div>before</div>
    <div class="folded">this is the hidden source code</div>
    <div class="info">N lines hidden</div>
    <div>after</div>
  </body>
</html>

You should be good with this CSS:

.folded {
  overflow: hidden;
  height: 0px;
}

.info {
  -moz-user-select: none;
  //add other browsers' variation
}

EDIT: another option (untested in Chrome)

HTML:

<html>
  <body>
    <div>before</div>
    <div class="folded">this is the hidden source code</div>
    <div class="info" data-lines='5'> </div>
    <div>after</div>
  </body>
</html>

CSS:

.folded {
  overflow: hidden;
  height: 0px;
}

.info:before {
  content: attr(data-lines) " lines hidden."
}
Jerome
  • 8,427
  • 2
  • 32
  • 41
  • Tried this without success (in Chrome, using -webkit-user-select). It turns out that while the replacement text is not selectable, it still gets copied:( Only way to cut it out of copying I've found is to put it as the value of a heavily-styled input tag. – larsrc Jul 17 '12 at 14:45
  • 1
    The overflow: hidden + height: 0px does not make the hidden text copyable in Chrome. – larsrc Jul 17 '12 at 14:58
  • See [stackoverflow.com/a/21884413/691281](http://stackoverflow.com/a/21884413/691281) for a way to make text visible but uncopyable in Chrome, Firefox and Safari. – John Mellor Feb 19 '14 at 15:19