OctavioSI OctavioSI - 4 months ago 12
CSS Question

Pagebreak in ContentEditable (WYSIWYG)

I am building a WYSIWYG editor for an web application which will simulate a "MS Word feel", that is, with the content being directly put inside a contenteditable element.

After much research, I was finally able to somehow "fake" a pagebreak between pages using a div element inside the contenteditable, built with two other float elements: (i) an element to push down the actual pagebreaker, such as a pseudo element would [the pagebreak-push]; and (ii) the pagebreak itself [the pagebreak-main]. The float pagebreak enables me to type text within the contenteditable in a way that the text will wrap around the pagebreak. Since the pagebreak is 100% width, text should only skip it.

This is what I got so far (JSFiddle: https://jsfiddle.net/OctavioSI/c19w68ff/10/):

HTML

<div class="wysiwyg-canvas">
<div class="wysiwyg-content" contenteditable="true">
Sample Text
<div class="pagebreak" contenteditable="false">
<span class="pagebreak-push"></span>
<span class="pagebreak-main" contenteditable="false">Pagebreak</span>
</div>
</div>
<div class="background-pages">
<div class="wysiwyg-page"></div>
<div class="wysiwyg-page pagespace"></div>
</div>
</div>


CSS

.wysiwyg-canvas{
background-color: #999999;
border:1px solid #cccccc;
padding:0.7vw;
overflow-y: auto;
height:400px;
width:100%;
position:relative;
font-size:1em;
}
.wysiwyg-page{
background-color: #FFFFFF;
border:1px solid #000000;
padding:0;
overflow: hidden;
cursor:text;
height:200px;
}
.wysiwyg-page.pagespace{
margin-top:5px;
}
.wysiwyg-content{
position:absolute;
top:5px;
left:5px;
width:calc(100% - 10px);
padding:0;
-moz-user-select: all;
-khtml-user-select: all;
-webkit-user-select: all;
user-select: all;
font-size:1em;
font-family: Verdana;
font-weight: normal;
color:#000000;
text-transform: none;
line-height:1em;
display:block;
border:1px solid green;
}
.pagebreak > .pagebreak-push{
float: right;
height:155px;
border:0;
width:1px;
display:block;
border-right:1px solid brown; /* Used for better view while testing */
}
.pagebreak > .pagebreak-main {
float:right;
clear:both;
width:100%;
height:50px;
margin: 0;
border:1px solid #aaaaaa; /* Used for better view while testing */
background-color:#cccccc;
line-height:50px;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
display:block;
}
.pagebreak {
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
display:block;
padding:0;
margin:0;
text-align:center;
color:#aaaaaa;
}
div:focus,
div:active,
div:hover {
text-decoration:none;
outline:none;
}


The Problem: The code itself works fine to a certain extent, as you can see in the JSFiddle and in the following screenshot (situation 1). Nonetheless, if I put the caret in the first position after the pagebreak and start typing, the text ends up being put inside the pagebreak space (in a vertical line, almost as if being put before the pagebreak) (situation 2). - Screenshot: Wrong behaviour after the pagebreak

My question is: is there any way to avoid this strange behaviour, thus making the text correctly skip the pagebreak without this glitch?

Some additional thoughts / info:


  1. After much digging on the topic, I have come up with the code above
    combining the idea of using a div with pseudo element (:before) so
    as to push it down and the idea that texts can be wrapped up around
    float elements. The reason I have used another element rather than
    the pseudo element approach is that I need to dynamically change
    this pagebreak-push element's height on window.resize. Since this
    proved to be difficult on the pseudo element, I decided to use this
    to emulate such effect.

  2. I have looked up CSS Regions, but since it was discontinued, I have
    discarded the idea. Then I found Adobe Polyfill CSS Regions, which seemed to be at first quite the answer to this: all I would need to do is define each page as a -adobe-flow-from and the text would flow though the pages. However, while I was able to flow the text on page load, setting the script to flow the text dynamically seems to be rather difficult. Even the workaround provided in the Polyfill documentation to update the layout rendered was not working in this scenario.

  3. Browser compatibility: This snippet is not working on Firefox or IE. As of Chrome, it was OK in Chrome v.50 (also OK in Chromium v49), but after updating the browser to the latest version v.51, the problem above started. Maybe this is some new way that Chrome is dealing with float objects? I am still trying to figure this out. Also, even in the events in which the text correctly skips the pagebreak, it will not skip if [Enter] is pressed -- only additional data, even if only [space].



Thanks in advance.

Answer

Try:

.wysiwyg-content div {
word-wrap: normal;
}

According to the link you provided, apparently they tweaked some functionalities of line wrapping with float 100% in the newest version of chrome. So maybe forcing the word wrapping to be normal might fix the problem.

Comments