Ran into a problem in JavaScript writing HTML code into innerHTML. Here is a very simple case I recreated. The problem is in the element style seems taking no effect, either using old font size or CSS style. The code has been tested on FireFox and Chrome in XAMPP localhost, and got same result. The text would be shown correctly but the style wouldn't. Any suggestion?
tDoc = document.getElementById('target');
tDoc.innerHTML = "<p><font size=' 5'>";
tDoc.innerHTML = document.getElementById("srcBox").value;
tDoc.innerHTML = "</font></p>";
tDoc.innerHTML = "<p style='font-size:20px;'>";
tDoc.innerHTML = document.getElementById("srcBox").value;
tDoc.innerHTML = "</p>";
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>JavaScript innerHTML not setting the element style</title>
</head>
<body>
<input type="text" name="ttBox" id="srcBox" value="My Title 2">
<div id="target">NA</div>
</body>
</html>
CodePudding user response:
Don't append to innerHTML
in multiple steps like that. Each time you assign to innerHTML
it parses the element completely to create the new DOM. If there are missing closing tags, it adds them. So when you do
tDoc.innerHTML = "<p><font size=' 5'>";
it's actually as if you did
tDoc.innerHTML = "<p><font size=' 5'></font></p>";
Then your next addition is outside the <font>
tag, so it doesn't get the style.
Put everything into a single string and assign it to innerHTML
all at once.
tDoc = document.getElementById('target');
let html = "<p><font size=' 5'>";
html = document.getElementById("srcBox").value;
html = "</font></p>";
html = "<p style='font-size:20px;'>";
html = document.getElementById("srcBox").value;
html = "</p>";
tDoc.innerHTML = html;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>JavaScript innerHTML not setting the element style</title>
</head>
<body>
<input type="text" name="ttBox" id="srcBox" value="My Title 2">
<div id="target">NA</div>
</body>
</html>
CodePudding user response:
Every time assign to the .innerHTML
of an element, the browser will do its best to make sense of the input and will produce markup as a result. If the input is malformed and not valid syntax, the browser will make what it can from it and do its best to produce valid elements and markup as a result.
The generated markup/elements will always be well-formed; at no point in the JavaScript is the structure in the DOM invalid.
When this line is run:
tDoc.innerHTML = "<p><font size=' 5'>";
The browser will see that there's no trailing <font>
or <p>
- but the resulting structure must be valid, so it ends those tags for you. After that line runs, the #target
element contains:
<p><font size=" 5"></font></p>
Then the next line runs:
tDoc.innerHTML = document.getElementById("srcBox").value;
But the browser has already ended the <p>
and <font>
tags - so that value doesn't get inserted inside those, but as a plain text node as a direct child of the #target
.
The pattern continues for the rest of your code.
Assign the HTML string all at once, so that the DOM structure isn't created piecemeal.
tDoc = document.getElementById('target');
tDoc.innerHTML = `
<p><font size=' 5'>
${document.getElementById("srcBox").value}
</font></p>
<p style='font-size:20px;'>
${document.getElementById("srcBox").value}
</p>
`;
<input type="text" name="ttBox" id="srcBox" value="My Title 2">
<div id="target">NA</div>
CodePudding user response:
You can't add partial tags to the DOM like that. The browser will not see the tags as belonging to a single element and possibly attempt to construct closing tags for the partial tag you append.
The simplest change is to add all of your HTML at once:
tDoc = document.getElementById('target');
tDoc.innerHTML = "<p><font size=' 5'>"
document.getElementById("srcBox").value
"</font></p>"
"<p style='font-size:20px;'>"
document.getElementById("srcBox").value
"</p>";
Additionally, you may want to escape the values obtained from the inputs. You can either manually escape them, or you can more effectively construct the individual DOM elements themselves rather than using a string.
tDoc = document.getElementById('target');
const p = document.createElement('p');
const font = document.createElement('font');
font.setAttribute('size', ' 5');
font.textContent = document.getElementById("srcBox").value;
p.appendChild(font);
const p2 = document.createElement('p');
p2.style.fontSize = '20px';
p2.textContent = document.getElementById("srcBox").value;
tDoc.innerHTML = '';
tDoc.appendChild(p);
tDoc.appendChild(p2);
The use of textContent
to insert the text will prevent the injection of text as HTML code that could manipulate the DOM and cause unexpected behavior.