You can use iframe
for this. This way, if the user modifies CSS, it will not compromise the main document.
Following basic code:
JavaScript:
function preview(input) {
const ta = document.querySelector("#ta2")
var preview = document.getElementById("preview")
ta.value = input.value
preview.contentWindow.document.open()
preview.contentWindow.document.write(ta.value)
preview.contentWindow.document.close()
}
CSS:
body {
font-family: Arial, Helvetica, sans-serif;
}
.container {
position: fixed;
top: 0;
left: 0;
width: calc(100% - 50px);
height: 100%;
padding: 25px;
}
.container-horizontal {
display: flex;
flex-direction: row;
border: 1px solid silver;
overflow: hidden;
xtouch-action: none;
height: calc(100% - 100px);
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
position: relative;
}
.container-vertical {
display: none;
flex-direction: column;
height: calc(100% - 100px);
border: 1px solid silver;
overflow: hidden;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
position: relative;
}
.esquerda {
flex: 0 0 auto;
/* only manually resize */
width: 50%;
min-height: 100%;
min-width: 150px;
max-width: 80%;
white-space: nowrap;
background: #eee;
color: white;
padding: 10px;
}
.direita {
border: none;
flex: 1 1 auto;
/* resizable */
padding: 10px;
width: 10%;
min-height: 100%;
background: #fff;
word-wrap: break-word;
overflow: auto;
}
.topo {
flex: 0 0 auto;
/* only manually resize */
padding: 10px;
height: 45%;
min-height: 10%;
max-height: 80%;
width: 100%;
white-space: nowrap;
background: #eee;
color: white;
}
.base {
flex: 1 1 auto;
/* resizable */
padding: 10px;
height: 10%;
width: calc(100% - 20px);
background: #fff;
word-wrap: break-word;
overflow: auto;
}
.divisor {
flex: 0 0 auto;
width: 10px;
background-color: #eee;
border: 2px solid #ddd;
cursor: col-resize;
}
.divisor-horizontal {
flex: 0 0 auto;
height: 10px;
background-color: #eee;
border: 2px solid #ddd;
cursor: row-resize;
}
.ta {
display: block;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
background: #eee;
color: #000;
resize: none;
border: none;
outline: none;
}
.botao {
display: inline-block;
height: 100%;
background: #0084FF;
color: #fff;
border: none;
border-radius: 3px;
margin-left: 8px;
padding: 10px;
font-size: 20px;
cursor: pointer;
float: left;
}
.botao-e {
display: inline-block;
height: 100%;
background: #0084FF;
color: #fff;
border: none;
border-radius: 3px;
margin-right: 8px;
margin-left: 8px;
padding: 10px;
cursor: pointer;
}
.botao-e i {
font-size: 20px;
}
.barra {
padding: 8px 0;
height: 40px;
width: 100%;
background-color: #ddd;
}
.float-right {
float: right;
}
.labelbarra {
padding: 13px;
font-weight: bold;
color: #555;
}
.inputbarra {
font-size: 20px;
padding: 8px;
width: 140px;
text-align: center;
border: 1px solid #ccc;
border-radius: 6px;
}
.pre-full {
position: fixed;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
z-index: 9999;
background-color: #fff;
}
.botao-flutuante {
position: absolute;
top: 5px;
right: 5px;
width: 30px;
height: 30px;
background: #0084FF;
color: #fff;
border: none;
border-radius: 3px;
font-size: 20px;
cursor: pointer;
padding: 5px;
}
.content:before {
content: '\e813';
}
/* ---------------------------------------------- */
.sw-tog {
position: relative;
display: inline-block;
width: 66px;
height: 40px;
float: left;
margin-left: 8px;
}
.sw-top input {
display: none;
}
.sli-tog {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #bbb;
-webkit-transition: .4s;
transition: .4s;
border-radius: 3px;
}
.sli-tog:before {
position: absolute;
content: "";
height: 28px;
width: 28px;
left: 6.5px;
bottom: 6.5px;
background-color: #fff;
-webkit-transition: .4s;
border-radius: 3px;
transition: .4s;
}
.tog:checked+.sli-tog {
background-color: #0084FF;
}
.tog:focus+.sli-tog {
box-shadow: 0 0 1px #0084FF;
}
.tog:checked+.sli-tog:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
#tempo-real {
display: inline-block;
margin: 12px;
float: left;
font-weight: bold;
font-family: 'Roboto', sans-serif;
color: #777;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
HTML:
<div class="container" id="container">
<div class="container-horizontal">
<div class="esquerda">
<textarea id="ta2" class="ta" oninput="preview(this)"></textarea>
</div>
<div class="divisor">
</div>
<button onclick="fullpage()" class="botao-flutuante"><i id="expand" class="fas fa-expand-arrows-alt"></i></button>
<iframe id="preview" class="direita" src="about:blank"></iframe>
</div>
</div>
Demo