Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: preserve html inside target elements #28

Merged
merged 12 commits into from
Jun 5, 2022

Conversation

lukePeavey
Copy link
Owner

@lukePeavey lukePeavey commented May 8, 2022

Summary

previously, all HTML inside the target element was stripped away when the text was split.

With this feature, HTML elements inside the target element(s) will be preserved when splitting text. This will make it possible to:

  • Apply custom styles to specific portions of the text
  • Include interactive elements such as links or buttons within split text

Example

<div id="target">Some <a href="#">active</a> text</div>
SplitType.create('#target', { types: 'lines, words, chars' })

Result

<div id="target">
  <div class="word" style="display: inline-block; position: relative">
    <div class="char" style="display: inline-block">S</div>
    <div class="char" style="display: inline-block">o</div>
    <div class="char" style="display: inline-block">m</div>
    <div class="char" style="display: inline-block">e</div>
  </div>
  <a href="#" style="display: inline-block">
    <div class="word" style="display: inline-block; position: relative">
      <div class="char" style="display: inline-block">a</div>
      <div class="char" style="display: inline-block">c</div>
      <div class="char" style="display: inline-block">t</div>
      <div class="char" style="display: inline-block">i</div>
      <div class="char" style="display: inline-block">v</div>
      <div class="char" style="display: inline-block">e</div>
    </div>
  </a>
  <div class="word" style="display: inline-block; position: relative">
    <div class="char" style="display: inline-block">t</div>
    <div class="char" style="display: inline-block">e</div>
    <div class="char" style="display: inline-block">x</div>
    <div class="char" style="display: inline-block">t</div>
  </div>
</div>

Limitations

1. Not fully compatible with splitting text into lines

If the content of a nested element spans multiple lines, it's not possible wrap each line and preserve the nested element. GSAP's plugin has the same limitation. There might be a way to solve this in the future. But for now, this feature will have the caveat that splitting lines is not fully supported.

However, nested elements can be used when splitting lines, as long as there are no line breaks in the nested elements.

TODO

  • Fix: Not working with absolute position.
  • Fix: Unexpected white space around nested elements (when splitting lines)
    Right now, when split lines is enabled, nested elements are always treated as a word boundary. This results in unwanted white space when nested elements do not align with a word boundary.
    For example:<p id="target"><em>foo</em>, barr</p>. In this case, there should be no space after the em; it should be immediately followed by a ",". Another example is nested elements that wrap part of a word: <p id="target"><em>Some</em>thing</p>.
  • Fix: Nested elements causing unexpected line breaks (when splitting lines)
    We use the offsetTop of each word to detect natural line breaks in the text. If the offsetTop of a nested element is slightly different than the previous word, it will trigger a line break. This often results in unwanted line breaks, especially with nested elements such as <button>. It should be possible to include nested elements that have padding/height/borders etc.
  • Add storybook examples and tests for this feature
  • Update documentation

For #3

previously, all HTML inside the target element was stripped away
when the text was split.

With this feature, nested HTML tags within the target elements
will be preserved.
lukePeavey added 11 commits May 11, 2022 22:55
Fixed: nested elements not working with position: absolute.

Fixed: unexpected white space around nested elements when split lines
is enabled. It will now maintain the original spacing even when nested
elements do not align with word boundaries. Examples:
`<p id="target">Fo<em>o</em> Bar</p>`
`<p id="target"><em>Foo</em>, bar</p>`

Fixed: nested elements causing unexpected line breaks when split lines
is enabled.  This was due to the way we detect line breaks. If the
`offsetTop` of a nested element was even slightly different than the
previous word, it would trigger a line break. This often resulted in
unwanted line breaks, especially when using nested elements such as
`<button>`. Now, we use a threshold (20% of font size) to determine
if a word/element is the start of a new line. In the future, we can
make that configurable via options.

Removed several unnecessary utility functions
Use Svelte as the framework for storybook examples instead of vanilla  HTML.
@lukePeavey lukePeavey merged commit 699446e into master Jun 5, 2022
lukePeavey added a commit that referenced this pull request Jun 5, 2022
Fixes two issues related to absolute position:

1. Text disappears when text is only split into lines, and the target
element does not contain any nested elements. This was a bug 
introduced by #28. 

2. Splitting text with absolute position slightly changes the visual
appearance of the text. This was due to the fact that we used
`offsetTop` and `offsetLeft`, which do not have sub-pixel precision.
Now, we use `getBoundingClientRect` to determine the position
of split text nodes. This has a slight negative impact on performance
(when absolute position is enabled), but it prevents the text from
from visibly shifting around when it is split/un-split.
@lukePeavey lukePeavey deleted the feature/preserve-html-tags branch June 13, 2022 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant