nightlock82 Posted January 3, 2023 Posted January 3, 2023 I'm doing a splitText specifically on separate characters on react. The issue is splitText uses divs to separate the characters instead of spans, this becomes a problem for screen-readers. I've tried applying the effect on the container and inline text but the output is still the same. Is there a way to make it into spans?
Solution Rodrigo Posted January 3, 2023 Solution Posted January 3, 2023 Hi @nightlock82 and welcome to the GreenSock forums! Your can specify the tag in the SplitText config object tag: String - by default, SplitText wraps things in <div> elements, but you can define any tag like tag: "span" Happy Tweening! 2
GreenSock Posted January 3, 2023 Posted January 3, 2023 Just so you know, the reason SplitText wraps things in <div> instead of <span> by default is because most browsers will not render transforms on elements that have display: inline (which is what spans do). So just be careful about that - if you try animating x/y/rotation/scale, for example, and it’s not working with <span>, that’s why. 1
nightlock82 Posted January 20, 2023 Author Posted January 20, 2023 @Rodrigo Thank you for that saved me a lot of time.
nightlock82 Posted January 20, 2023 Author Posted January 20, 2023 @GreenSock I noticed this happening. Are there any possible workarounds I saw some samples from websites on awwwards for example but I couldn't understand how they were doing this. My main concern with <div>'s is the accessibility, a screen reader would read it on a per-letter basis and that's a real head-scratcher.
Rodrigo Posted January 20, 2023 Posted January 20, 2023 Hi, I'm not an a11y expert at all, but you could check if the user is on a screen reader and revert the SplitText instance or perhaps never create it? I would try that. Maybe I'm wrong in my consideration, but a text being animated letter by letter is not something super useful on a screen reader, right? Again I know virtually nothing about a11y so I'm just proposing an idea based on zero knowledge and just what I consider kind of useful on the particular scenario of a screen reader. Hopefully this helps. Happy Tweening!
GreenSock Posted January 21, 2023 Posted January 21, 2023 I guess you could try setting display: inline-block on the <span> to make them work with transforms. I’m half-conscious in bed with COVID on my iPad, so I can’t verify at the moment, but you could give it a shot. 1
Cassie Posted January 21, 2023 Posted January 21, 2023 Quote My main concern with <div>'s is the accessibility, a screen reader would read it on a per-letter basis and that's a real head-scratcher. Nah there's tons of ways round this! One route is doubling up content. You visually hide one so sighted people don't see it, but screenreaders read it out still, then whack aria-hidden on the one that's being split. https://www.a11yproject.com/posts/how-to-hide-content/#:~:text=visually-hidden class is applied,focus indicator had gone to. <h2 class="visually-hidden">This is a sentence</h2> <h2 class="split" aria-hidden="true">This is a sentence</h2> .visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } Another option is using aria hidden on the header and an aria label and role on a containing div <div role="heading" aria-level="2" aria-label="word"> <h2 class="title" aria-hidden="true"> <div>w</div> <div>o</div> <div>r</div> <div>d</div> </h2> </div> Another one would be to loop round the children that splittext creates and whack aria-hidden on them and an aria label on the text element. I raised this casually with Jack the other day about seeing if we can bake an option in so it's a little easier for people. Either way though, plenty of ways around this! 3
Cassie Posted January 22, 2023 Posted January 22, 2023 Here's a demo of the best (but more fiddly) way. Ideally you'd have an aria label on the text element itself rather than assigning aria attributes to a non semantic element like a div. So something like this. I would go for this route with headings, but I'd likely duplicate text for long sections of text like paragraphs. Kapture 2023-01-22 at 09.43.42.mp4 Another route I've gone in the past is adding aria-hidden on split text elements, then calling revert on them once they've animated in and removing the aria-hidden. Like so... See the Pen poZaJQa?editors=1010 by GreenSock (@GreenSock) on CodePen. Obviously all these routes are worth testing with folks that actually use screenreaders if you have the capacity to do so. 3 1
nightlock82 Posted January 24, 2023 Author Posted January 24, 2023 Oh, I haven't been on for a bit, thank you folks for the responses. ❤️ Gonna try it out and see this is awesome. 1
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 On 1/3/2023 at 12:23 PM, Rodrigo said: Hi @nightlock82 and welcome to the GreenSock forums! Your can specify the tag in the SplitText config object tag: String - by default, SplitText wraps things in <div> elements, but you can define any tag like tag: "span" Happy Tweening! There is no option for "tag", Chrome is complaining that i cannot have Divs inside a <p> tag, so it need it to be a span
Rodrigo Posted May 23, 2023 Posted May 23, 2023 Hi @Levin Riegner, In the config object passed to the SplitText constuctor, from the SplitText docs: tag String - by default, SplitText wraps things in <div> elements, but you can define any tag like tag: "span" const split = new SplitText(yourElement, { tag: "span", }); Hopefully this helps. Happy Tweening!
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 1 hour ago, Rodrigo said: Hi @Levin Riegner, In the config object passed to the SplitText constuctor, from the SplitText docs: tag String - by default, SplitText wraps things in <div> elements, but you can define any tag like tag: "span" const split = new SplitText(yourElement, { tag: "span", }); Hopefully this helps. Happy Tweening! This doesnt work for me
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 Heres my example code: // Imports // ------------ import React, { useRef, useLayoutEffect } from 'react'; import { gsap } from 'gsap'; import { SplitText } from 'gsap/all'; // Styles // ------------ import { Jacket } from './styles'; // Component // ------------ const ScrollAnimatedText = ({ children }) => { // NOTE • refs const comp = useRef(); // NOTE • Animation useLayoutEffect(() => { let timer; let split; const ctx = gsap.context(() => { timer = setTimeout(() => { const childText = comp.current.firstChild; split = new SplitText(childText, { tag: 'span', type: 'lines,words,chars', linesClass: 'line', }); const lines = comp.current.querySelectorAll('.line'); for (const line of lines) { gsap.to(line, { ease: 'none', opacity: 1, y: `0%`, scrollTrigger: { trigger: line, start: 'top bottom', end: 'top top+=60%', scrub: true, markers: false, }, stagger: { each: 0.08, from: 'start', }, }); } }, 150); }, comp); return () => { clearTimeout(timer); ctx.revert(); }; }, []); return <Jacket ref={comp}>{children}</Jacket>; }; export default React.memo(ScrollAnimatedText);
Rodrigo Posted May 23, 2023 Posted May 23, 2023 Hi, Without a minimal demo there is not a lot we can do. This starter template has the GSAP Trial package so you can run the bonus plugins and tools: https://stackblitz.com/edit/react-iqmjfx Also I'm curious about why you're running that setTimeout inside the effect hook ?♂️ Also you can replace this: const lines = comp.current.querySelectorAll('.line'); With this: const lines = gsap.utils.toArray('.line'); Inside the GSAP Context instance you already defined a scope, to the toArray() method knows exactly where to look for that selector. Happy Tweening!
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 Im having to run a settimeout, as for some reason, without it gsap doesnt seem to render any animations
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 Without the settimeout splittext puts single words onto different lines for some bizarre reason
Rodrigo Posted May 23, 2023 Posted May 23, 2023 1 minute ago, Levin Riegner said: Im having to run a settimeout, as for some reason, without it gsap doesnt seem to render any animations That's odd ? Please create a minimal demo so we can take a better look. Happy Tweening!
Levin Riegner Posted May 23, 2023 Posted May 23, 2023 Im not sure how to recreate it outside of my react application - where do you usually import SplitText from with the business account?
Rodrigo Posted May 24, 2023 Posted May 24, 2023 Hi, If you check the template I linked before: https://stackblitz.com/edit/react-iqmjfx You'll see that the import comes from the GSAP Trial package: import gsap from 'gsap-trial'; import { ScrollTrigger } from 'gsap-trial/ScrollTrigger'; import { SplitText } from 'gsap-trial/SplitText'; Just fork that example and a minimal representation of your setup. Please don't include all your code as it will take longer to find the issue, just the pertinent part of it that's causing the problem you're facing. Happy Tweening!
Levin Riegner Posted May 24, 2023 Posted May 24, 2023 Why would i use the trial in my build when i pay for greensock?
Rodrigo Posted May 24, 2023 Posted May 24, 2023 That's just for the stackblitz template not your setup. There's no other way to use the bonus tools there. In your setup keep using the files you download or the npm token
GreenSock Posted May 24, 2023 Posted May 24, 2023 Seems to work fine - am I missing something?: See the Pen WNaPMRV?editors=1010 by GreenSock (@GreenSock) on CodePen. Keep in mind that browsers won't honor transforms on display: inline elements. That has nothing to do with GSAP - it's just how CSS works. Just set them to inline-block then. 1
Levin Riegner Posted May 24, 2023 Posted May 24, 2023 The problem here is youre importing splittext, but not from the import library, it seems to work when i create it in codepen with the trial, but not with the import in my react project
Levin Riegner Posted May 24, 2023 Posted May 24, 2023 After a reinstall of NPM today, everything is now working again
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now