Simple terminal style message logger
You're using the right approach with the log - you're saving it in a variable so you don't have to select the element again. Do the same thing with the newly appended &lt;div&gt;.


const log = $('#log')

function logMessage(message, type) {
    const newDiv = $('&lt;div&gt;&lt;/div&gt;')
      .addClass(type)
      .appendTo(log);
    for (let charIndex = 0; charIndex &lt; message.length; charIndex++) {
        setTimeout(() =&gt; {
            newDiv.append(message[charIndex])
        }, charIndex * 10)
    }
}

logMessage('something with lots and lots and lots and lots of characters', 'sometype');
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div id="log"&gt;&lt;/div&gt;



A tiny issue with iterating over the indicies of the string manually is that characters composed of surrogate pairs (like ) will take twice as long to print as others, and if you were to slow down the animation, you'd get a broken character before the second part gets fully rendered:


const log = $('#log')

function logMessage(message, type) {
    const newDiv = $('&lt;div&gt;&lt;/div&gt;')
      .addClass(type)
      .appendTo(log);
    for (let charIndex = 0; charIndex &lt; message.length; charIndex++) {
        setTimeout(() =&gt; {
            newDiv.append(message[charIndex])
        }, charIndex * 500)
    }
}

logMessage('something with lots and lots and lots and lots of characters', 'sometype');
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div id="log"&gt;&lt;/div&gt;



It also might be useful to return a Promise indicating that the message has been fully logged, instead of a number indicating how long to wait before the message is finished.
To tweak this, and to avoid having to touch the string indicies at all (since you only really care about the characters, not the indicies of characters) would be to invoke the string's iterator and await a Promise inside the loop:


const log = $('#log');
const delay = ms =&gt; new Promise(resolve =&gt; setTimeout(resolve, ms));

async function logMessage(message, type) {
    const newDiv = $('&lt;div&gt;&lt;/div&gt;')
      .addClass(type)
      .appendTo(log);
    for (const char of message) {
        newDiv.append(char);
        await delay(500);
    }
}

logMessage('something', 'sometype')
  .then(() =&gt; {
      console.log('message fully printed');
  });
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;
&lt;div id="log"&gt;&lt;/div&gt;



I'm a bit worried about the log ID - you have both a global identifier log which refers to the HTMLElement and exists on the window. Then the code shadows the global identifier and creates a log which refers to the jQuery collection. It's an unlikely source of bugs, but I'd use a class instead of an ID.
I notice you're not using semicolons. If this is a deliberate style choice and you consider yourself an expert who can avoid the pitfalls of Automatic Semicolon Insertion, that's just fine. Otherwise, you may occasionally run into very confusing bugs due to a statement unexpectedly crossing a linebreak, and I'd recommend using them.