Steer clear of dividing words

I am attempting to showcase sentences letter by letter with a fade in/fade out effect. However, I am facing an issue where words break in the middle. How can this word breaking be prevented?

var quotes = document.getElementsByClassName('quote');
var quoteArray = [];
var currentQuote = 0;
quotes[currentQuote].style.opacity = 0;
for (var i = 0; i < quotes.length; i++) {
  splitLetters(quotes[i]);
}
function changeQuote() {
  var cw = quoteArray[currentQuote];
  var nw = currentQuote == quotes.length-1 ? quoteArray[0] : quoteArray[currentQuote+1];
  for (var i = 0; i < cw.length; i++) {
    animateLetterOut(cw, i);
  }
  for (var i = 0; i < nw.length; i++) {
    nw[i].className = 'letter behind';
    nw[0].parentElement.style.opacity = 1;
    animateLetterIn(nw, i);
  }
  
  currentQuote = (currentQuote == quoteArray.length-1) ? 0 : currentQuote+1;
}
function animateLetterOut(cw, i) {
  setTimeout(function() {
cw[i].className = 'letter out';
  }, 0);
}
function animateLetterIn(nw, i) {
  setTimeout(function() {
nw[i].className = 'letter in';
  }, 340+(i*30));
}
function splitLetters(quote) {
  var content = quote.innerHTML;
  console.log(quote.innerHTML);
  quote.innerHTML = '';
  var letters = [];
  for (var i = 0; i < content.length; i++) {
    var letter = document.createElement('span');
    letter.className = 'letter';
    letter.innerHTML = content.charAt(i)==' '?'&nbsp;':content.charAt(i);
    quote.appendChild(letter);
    letters.push(letter);
  }
  
  quoteArray.push(letters);
}
changeQuote();
setInterval(changeQuote, 10000);
body {
  font-weight: 600;
  font-size: 40px;
}
.text {
  position: relative;
}
.quote {
  position: absolute;
  opacity: 0;
}
.letter {
  display: inline-block;
  position: relative;
  float: left;
  -webkit-transform: translateZ(25px);
          transform: translateZ(25px);
  -webkit-transform-origin: 50% 50% 25px;
          transform-origin: 50% 50% 25px;
}
.letter.out {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s 0.7s, opacity 0.7s linear;
}
.letter.behind {
  visibility: hidden;
  opacity: 0;
}
.letter.in {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.7s linear;
}
<body>
<div class="text">
  <p>
    <span class="quote">TEXT ONE(1): For example, if you are designing a brand new website for someone, most times you will have to make sure the prototype looks finished by inserting text or photos or what have you. </span>
    <span class="quote">TEXT TWO(2): The purpose of this is so the person viewing the prototype has a chance to actually feel and understand the idea behind what you have created.</span>
  </p>
  
</div>

Answer №1

Your setInterval(changeQuote, 5000) is responsible for the unique effect you have skillfully implemented in a concise manner. Initially playing around with the timing intervals from 5000ms to 15000ms down to approximately 8000~10000ms seemed to yield the best results.

Try changing it to setInterval(changeQuote, 9000) and observe the difference.

However, considering scalability, there needs to be a way to ensure that the setInterval function waits until the quoteArray has completed pushing all the letters.

MODIFICATION

Based on the valuable feedback provided in the comments, I deduced the following:

  • From a JavaScript standpoint, each letter in the sequence is encapsulated within a <span> element, thus serving as individual entities. What was missing was the ability to group these letters into words to enable proper formatting according to their parent container.

In terms of CSS styling, the container housing the letters, known as quote, required specific styles to accurately represent its contents. By incorporating properties such as white-space: nowrap and display: block, I was able to provide a flexible container for its children to adjust based on screen width.

Refer to the corrected snippet below for further clarification.

var quotes = document.getElementsByClassName('quote'),
  quoteArray = [],
  currentQuote = 0;

quotes[currentQuote].style.opacity = 0;

for (var i = 0; i < quotes.length; i++) {
  splitLetters(quotes[i]);
}

function changeQuote() {
  var cw = quoteArray[currentQuote];
  var nw = currentQuote == quotes.length - 1 ? quoteArray[0] : quoteArray[currentQuote + 1];
  for (var i = 0; i < cw.length; i++) {
    animateLetterOut(cw, i);
  }
  for (var i = 0; i < nw.length; i++) {
    nw[i].className = 'letter behind';
    nw[0].parentElement.style.opacity = 1;
    animateLetterIn(nw, i);
  }

  currentQuote = (currentQuote == quoteArray.length - 1) ? 0 : currentQuote + 1;
}

function animateLetterOut(cw, i) {
  setTimeout(function() {
    cw[i].className = 'letter out';
  }, 0);
}

function animateLetterIn(nw, i) {
  setTimeout(function() {
    nw[i].className = 'letter in';
  }, 340 + (i * 30));
}

function splitLetters(quote) {
  var content = quote.innerHTML,
  words = [],
      word = document.createElement('span');
  
  word.className = "word";
  word.innerHTML = "";
  quote.innerHTML = "";
  
  for (var i = 0; i < content.length; i++) {
    var letter = document.createElement('span');
    letter.className = 'letter';
    
    if(content.charAt(i) !== " "){
    letter.innerHTML = content.charAt(i);
      word.innerHTML = word.innerHTML.concat(letter.innerHTML);
    }
    else {
    letter.innerHTML = "&nbsp";
      word.innerHTML = word.innerHTML.concat(letter.innerHTML);
      quote.appendChild(word);
      words.push(word);
      word = document.createElement('span');
      word.className = "word";
    }
  }

  quoteArray.push(words);
}
changeQuote();
setInterval(changeQuote, 10000);
body {
  font-weight: 600;
  font-size: 40px;
}

.text {
  position: relative;
}

.quote {
  position: absolute;
  display: block;
  opacity: 0;
  white-space: nowrap;
}

.letter {
  display: inline-block;
  position: relative;
  float: left;
  -webkit-transform: translateZ(25px);
  transform: translateZ(25px);
  -webkit-transform-origin: 50% 50% 25px;
  transform-origin: 50% 50% 25px;
}

.letter.out {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s 0.7s, opacity 0.7s linear;
}

.letter.behind {
  visibility: hidden;
  opacity: 0;
}

.letter.in {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.7s linear;
}
<div class="text">
  <p>
    <span class="quote">TEXT ONE(1): For example, if you are designing a brand new website for someone, most times you will have to make sure the prototype looks finished by inserting text or photos or what have you. </span>
    <span class="quote">TEXT TWO(2): The purpose of this is so the person viewing the prototype has a chance to actually feel and understand the idea behind what you have created.</span>
  </p>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JSX refusing to display

Currently, I am enrolled in an online course focusing on React and Meteor. Despite successfully registering a new player in the database upon hitting the submit button, the client side fails to display the information. Upon checking the console, the foll ...

Running a 2D JavaScript game script on a React page - A step-by-step guide!

I am facing a challenge with my website that features a game coded entirely in javascript. Despite my efforts to switch the site from an HTML layout to a more modern React design, I can't seem to get the game to display correctly. In the original HTM ...

What is the method for including HTML special characters in d3.js?

I am attempting to incorporate the degree symbol in my HTML code using ° const degreeNum = d3 .select(`#windBox${order}`) .append("text") .attr("x", 250) .attr("y", 130) .style("font", "bold 50px sans-serif") ...

Issues arise when incorporating background images with bootstrap 3

Currently working on designing a responsive layout for an online clothing store using Bootstrap 3. One of the requirements is to use background images inline styles for product containers. However, facing difficulty styling the containers and images to ach ...

Apply CSS code to create a fading effect for a container

Below is the code for my accordion list, created using only CSS and HTML. Whenever a heading is clicked, the text slides in with a different background color. How can I make it so that the container with the text and different background color fades in and ...

Is there a way for me to stack the submenu links on top of each other?

Is there a way to rearrange the submenu links so they appear stacked vertically instead of horizontally? Currently, they line up next to each other under the main menu and subsequent links fall below the submenu. I believe it involves adjusting the positio ...

Creating a Custom Rule for Checkbox Validation using jQuery

Can the jQuery Validation plugin be used to validate custom values on checkboxes, rather than just True or False? For instance: <input id="test" type="checkbox" name="test" value="something"> I am struggling to find a method that can check if &apo ...

Transform JSON data into a JavaScript variable

Just diving into the world of Node.js and JavaScript. Please forgive me if my question seems basic. Here is a snippet of my Node.js code that retrieves data from MySQL: var quer = connection.query('select password from users where mail="' ...

Effortless AJAX Submission and MySQL Data Refresh

I've hit a roadblock and can't seem to figure things out. I'm getting rid of my current code because it's not working well across different browsers, particularly when it comes to ajax submission. Could someone please provide me with a ...

Display substitute text for the date input field

When using input types date and datetime-local, the placeholder attribute does not work directly. <input type="date" placeholder="Date" /> <input type="datetime-local" placeholder="Date" /> Instead, the ...

What sets xhr.response apart from xhr.responseText in XMLHttpRequest?

Is there any difference between the values returned by xhr.response and xhr.responseText in a 'GET' request? ...

How can I increase the element by $100 using a dropdown selection in JavaScript?

Hey there! Looking to create a dropdown list with two shipping options: Special Shipping Normal Shipping <select> <option>Special Shipping</option> <option>Normal Shipping</option> </select> If the user selects Speci ...

Tips for creating a personalized dialog box after logging in with React Admin based on the server's response

One of my requirements is to allow users to select a role during the login process. Once the user enters their username and password, the server will respond with the list of available roles. How can I implement a dialog where the user can choose a role fr ...

Learn how to retrieve a jqGrid ajax Nested Array of Json string in C# using Newtonsoft Json

I am attempting to parse a JSON string and extract the array values within it. {"_search":true,"nd":1492064211841,"rows":30,"page":1,"sidx":"","sord":"asc","filters":"{\"groupOp\":\"OR\",\"rules\":[{\"field\":\ ...

What is the best way to retrieve properties from a different module in JavaScript?

I have a module named ProgressIndicator: ... export default class ProgressIndicator { constructor() { ... const indicatorGeometry = new THREE.PlaneGeometry(2, 2, 1, 1) const indicatorMaterial = new THREE.ShaderMate ...

What is the best method to insert multiple rows of the same height into a table cell in

My datatable is causing me trouble as I try to add more rows in the td after the Name column. The rows are not aligning properly, and I need a solution. I want these new rows to be aligned with each other, but the number of rows may vary based on user inp ...

Vibrant diversity in a solitary symbol

I have customized styles to incorporate Fontawesome icons with their brand colors - for instance, the Opera icon appears in red, IE in blue, and Firefox in orange. Chrome, however, presents a unique challenge with its four distinctive colors. I am curious ...

Looking for a way to efficiently sort through props in Next.js? Struggling with filtering data within props from componentDidMount in Next.js?

I retrieve data into the props of my component using getStaticProps. However, I need to filter this data before utilizing it in the component. Typically, I would do this in componentDidMount, but it appears that the props are populated after componentDidMo ...

What is the best way to retrieve user data for showcasing in a post feed using firebase's storage capabilities?

I'm currently developing a forum-style platform where users can share content that will appear on a universal feed. I intend to include user details in the posts (such as photoURL and displayName) similar to how it is done on Twitter. For this projec ...

What is the process of importing a cascading style sheet into a C# object?

Currently, I am working on a web application and I would like to provide users with the flexibility to change the styling elements of CSS linked to a page through an admin screen. I have been exploring ways to load a CSS file into a C# object or convert ...