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

Allow users to override the display and position style on nested elements #69

Open
robinpoort opened this issue Nov 23, 2023 · 9 comments

Comments

@robinpoort
Copy link

Hey there, great plugin!

I did run into a little issue though which might be fixable?

When another element is being found you make sure to preserve that element; which is great. However the fact that splitType is giving these elements inline styling for display and position is a bit less great ;) These elements also don't get any classname so we can't override them with !important (not that we want that, but even this is not an option).

Here's a quick codepen illustrating the issue:
https://codepen.io/robinpoort/pen/mdvLaKW

As you can see, the span element inside the h2 get display: inline-block and position: relative applied to it. Even if the span has a class that has other values (the second example), these values will simply be overwritten. In my case (the real project i'm working on) the span can't even have a class since the headings are coming from a system I have little control over :(

I can think of a few possible solutions:

  1. Instead of using inline styles; add a class that has position: relative; display: inline-block; so this class is easily overwriteable. This solution would not be optimal since you can't target individual instances on the page this way.
  2. Next to the types option add a 'inline-styleoption where you can assign a list likeinline-block, relative(the default) but alsoinline, staticorblock, sticky` for example. This would be a nice addition since you can style different instances on the page accordingly.
  3. A third option might be to be to add the ability to add a custom class to these span elements. This way we can use !important to override the default behavior. Either that; or remove the inline styling when a custom class is set so you can set your own.

Would any of the above even be possible?

Not sure if this is clear or not. Let me know if you need more explanation or examples :-)

@lukePeavey
Copy link
Owner

lukePeavey commented Nov 23, 2023

I will follow up with a more detailed response later.

briefly, those two styles are required for the library to work. Block level html elements are not supported inside the target elements. It only supports inline block elements inside the target element. As a potential alternative, you can target each of the block level elements that contain the text content, instead of targeting their parent container.

https://codepen.io/lukePeavey/pen/xxMjevw

Screenshot 2023-11-23 at 4 12 15 PM
 <h2>
    <span>Lorem ipsum</span>
    <span>without the split plugin<span>
  </h2>
SplitType.create("h2 span", { types: 'words' });

@robinpoort
Copy link
Author

Hi Luke,

Thanks for the reply!

Those styles are required during calculations then? Would it at least be possible to assign a class to it so it would be possible to apply styling; even if it needs !important to overrule the inline styles? If that is not possible due to calculations being miscalculated; might it be possible to add the class when calculations are done? And even temporarily remove them on recalculation if that occurs (like on a page resize for lines etc.)? It would help me tremendously to target the differtn splits occuring on the page :-)

Unfortunately I do not have any control over the markup at this point. So I have to do it all with JS / CSS at the moment so I'll try to come up with an alternative fix for now :-)

Alrighty, keep up the great work!

@lukePeavey
Copy link
Owner

lukePeavey commented Nov 28, 2023

I took a look at the code. I think we can figure out a way to support what your asking for...

first, its not necessary for the library set display: inline-block on existing elements.
Existing elements inside the target element can be either inline-block or block. In both cases, there are limitation when splitting text into lines (splitting into lines will only work if there are no line breaks inside nested elements).

Other display values are not supported and will likely break the visual appearance of the text and/or cause unexpected results. This includes flex and inline-flex.

Anyway, I agree that people should be able to set the display style themselves to best suit their needs.

The other property is a bit trickier. Nested elements inside the target elements need to have position set to relative or absolute. The way the library currently computes the locations of line breaks, the size and position of text elements (when using absolute true), depends on nested elements having a set position.

In most cases, this should be set to relative. I'm not sure if the library will work as expected if the target element contains a child element that is absolutely positioned. But we can provide an option so people can override this style if people want to try this.

I will think about how to implement this, just wanted to give you a quick update

@robinpoort
Copy link
Author

Great to hear, and thanks for the update :-)

Of course; line splitting is a little different in that regard.

And yeah, display: flex and display: grid could result in very strange results. However, I can think of use-cases where even they might be nice to have from some people (not for me though). For example, if you'd like to only split characters and then place them inside a grid or something. However, this might be something so specific that it is better to write a little JS yourself to only split the characters which is way less complicated than also splitting words and especially lines :)

As for position: absolute; one example could be to have an icon inside a heading like this for example:

<h1>
    <svg>...</svg>
    Title
</h1>

Where the svg has position: absolute; to be positioned while the h1 itself has a padding-left for example. However, this can be solved in a myriad of other ways as well. Also, position: absolute is not something I need. I just included it in the first example since it's an inline style that can't be easily overwritten. :)

And of course, some things just aren't possible, at least not in a way while keeping the code light enough for the majority of use-cases 👍

@lukePeavey
Copy link
Owner

lukePeavey commented Nov 28, 2023

Yeah that makes sense. The svg icon is a good example.

A few options... These would all be pretty easy to implement. Let me know what you think, or if you have other suggestions.

  1. instead of setting inline styles, we could add a prefixed class name to nested elements, as you suggested. This would allow users to override the styles using important or selector specificity.

  2. We could define css variables for the display and position values of nested elements. These would be set to the current values by default. Users could override them for specific elements by setting the variable within that scope.

.myAbsoluteElement {
  --splitType-nestedElementPosition: absolute;

// ... styles 
}

.myBlockElement {
  --splitType-nestedElementDisplay: block;

// ... styles 
}
  1. we could add an option to prevent splittype from setting any styles on existing elements. This would allow users to style these elements themselves without needing to use important.

@robinpoort
Copy link
Author

Option 1

I like this idea since it gives the plugin the possibility to work correctly but also gives the developer options to overwrite. However a big downside might be that you get unexpected results since the existing class might have higher specificity for display like flex for example. If you go for option 1 I'd suggest to add this as an option so using the plugin by default gives expected results. Only if the developer chooses class instead of inline for example the change should occur. Just to make sure to keep support at a minimum ;)

Option 2

Quite like this as well. Would you assign these in a global :root Or add them to each splittype 'parent'? Assigning to root resulting in fewer lines of inline code. With this option the values will still be inline I presume? But in this case just easily overwriteable. Not 100% sure what the benefit might be here over just a simple class name. We're not talking about global changing variables like color, spacing units or other 'theme like' variables, so custom properties might be a little bit overkill?

Option 3

I guess this is the behavior that I expected originally. However if you say that both the inline-block and relative position are needed for the plugin to work this option might add a lot of confusion when enabled?

Conclusion

I think option 1 would be the best option. Added as an optional setting so the core plugin just works as expected. When enabling you get the class names instead of inline styling which can then be easily overwritten (just make sure you keep the lowest specificity possible) while making sure the plugin functions just fine in 90% of the cases (when there's no position and display specificity issues) as opposed to option 3. You could choose option 2 since it's more modern, but I personally do not see the benefit in this case.

The code for option 1 could be (121 characters, including override):

<div class="classname"></div>
.classname {
  position: relative;
  display: inline-block;
}

Override:

.my .classname {
  display: block;
}

The code for option 1 could be (204 characters, including override):

<div style="position: var(--splittype-position); display: var(--splittype-display);"></div>
:root {
  --splittype-position: relative;
  --splittype-display: inline-block;
}

Override

.my {
  --splittype-display: block; 
}

Seeing this written out, it doesn't make such a big difference. It's also depending on what the class name is going to be and what the custom properties are going to be named.

All you can say about it now is that option 1 might look a little cleaner in devtools since it's just the classname. But option 2 is a little bit more modern if you're into that :)

@lukePeavey
Copy link
Owner

Sounds good to me, let's go with option 1.

I am working on another PR to update the dev dependencies. I will merge that before we start on this.

If you are interested in working on this feel free to submit a PR

@robinpoort
Copy link
Author

Awesome!

And I would if I thought I could, but the JS you wrote is a bit above my skill level ;) I'm mostly a designer / markup / CSS guy that writes (and copy-pastes) a little bit of JavaScript every now and then :)

@lukePeavey
Copy link
Owner

No worries! I should be able to get this done pretty soon.

@lukePeavey lukePeavey changed the title Optional style settings Allow users to override the display and position style on nested elements Nov 28, 2023
@lukePeavey lukePeavey self-assigned this Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants