I've been working with contenteditable recently within a HTML5 page and encountering bugs when using it with certain elements, and I'd like to know where and how I can actually safely use it.
I've discovered that making a span element contenteditable results in some buggy behaviour in both Firefox1 and Chrome2. However, making a div or section contenteditable appears completely safe3.
A guideline a couple of people have mentioned is that only block-level elements should be made contenteditable. However, the Mozilla Developer Network lists the heading elements h1 through to h6 as block-level elements, and making a heading element contenteditable is buggy in Firefox4 and can crash the page in Chrome5.
I'd like to be able to use more than just divs and sections, but I'm not clear on what elements I can actually safely make contenteditable. By safely, I mean that using the element under normal conditions, I should be able to perform normal editing tasks without it doing unexpected or buggy things. I should be able to write in it, delete content, cut, copy, paste, and move my text cursor about and highlight text without unexpected or strange behaviour.
So, which elements can I really make contenteditable safely? Is there a specific category? Are there certain criteria the safely-contenteditable element must match?
Bug notes:
Firefox 21 w/ span: Element loses focus if the text cursor is brought to the beginning or end of the element, but not if it got there by deleting content. Highlighting part of the element, cutting and then pasting will split the element in two at that point then insert a blank element between the two parts - without actually putting the text you were trying to paste anywhere.
Chrome 27 w/ span: If the span covers multiple lines e.g. by being wordwrapped, cutting and pasting content will often insert a linebreak after the pasted content.
Unless you make the div display:inline, in which case it can still lose focus as in 1, but apparently only if you bring the text cursor to the end. I don't consider this "normal" usage of the element though.
Firefox 21 w/ heading: Selecting part of the content then cutting and pasting will, similarly to 1, split the heading element in half at that point, and insert a third heading element between the two halves. It will, at least, have your pasted content inside it, but now you have three heading elements where there was originally one.
Chrome 27 w/ heading: Select some content and cut and paste. The page crashes. You get an "Aw snap!" message. That's it.
Demo code
Here's a demo for reproducing the above. It's pretty simple, though at the moment the only thing it isn't reproducing is the lose-focus bug.
[contenteditable=true] {
border: 1px dotted #999;
}
<article style="width: 100px">
<h1 contenteditable="true">Heading</h1>
<p>
<strong>Some adjacent content</strong>
<span contenteditable="true">Span! This is long enough it will spread over multiple lines.</span>
</p>
<div style="display: inline" contenteditable="true">An inline div also with multiple lines.</div>
</article>
In my opinion, I'd say div is the safest bet across the board. Any element you wish to truly edit (be it a span, header, etc), you can place inside the div and edit as if it were just that element. Also, to account for the display:inline issue you mentioned, you could always use float:left or float:right on your editable div to give it an "inline feel" without having it actually be inline.
Hope that helps!
Since this is an evolving feature with, apparent, low priority from the browser vendors support has been sketchy and regressions not uncommon. The current state of affairs is evolving, so check the Googles, CanIUse etc and make sure support is there for your sites visitors, everything else is moot ...
Support in Firefox seems to be solid, at least for some elements, now https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
It works well in Chrome as well as far as my testing goes.
And CanIUse looks good: http://caniuse.com/#feat=contenteditable
There are a number of different bugs related to the feature in the different browsers though, but for simple use cases it should be ok now, as of August 2016.
Related
I am trying to create a link that goes directly to a certain section of a different page. Here is what I'm doing.
I create an anchor point using the name attribute:
<a name="fish"></a>
<p>some content....</p>
I create a link with the # added to the end
"http://example.com#fish"
***note I have also tried the id method instead of name which still gives me the same issue.
example: <div id="fish"></div>
The functionality works fine and it takes me to the specific part on the page, the only issue is that it looks different on different browsers. What firefox displays is about 5 inches higher than what chrome displays.
It's probably because the a tag is taking up some space.
Easiest solution, use an id instead.
<p id="fish">some content....</p>
Make sure there's enough content below so it can scroll
Most browsers have the same css default value for common html elements, however it is possible that some elements have different attribute values for padding and margin.
One way to avoid these differences is explicitly applying the values in the css statements.
p {margin: 10px 0px}
If you do not want to do this, I recommend you put link exactly in the position where text is located.
<p><a name="fish"></a>some content....</p>
You can locate the link anywhere since the anchor element will not be visible in the viewport
the following tag works, except it adds heading level 4 at the end of the entries on aria-tab
<h4 ng-if="voiceOver" class="keep-it-classy" ng-bind="getCurrentText()" aria-label="{{getCurrentText}}"></h4>
is there some way to stop it reading the header size outloud?
Headings allow for more structural, simpler navigation. Telling a user that something is a heading, is telling them that if they use heading navigation, they can easily return to this spot.
So the announcement:
heading level 4
Is very useful. It tells them that they are at a structurally important part of the page. It also tells them, that if they set the rotor to "headings" they can easily return to this spot by flicking up/down.
Now, this is all assuming that your tag is structurally important, and behaving as an actual heading, and not just pretty text. In this case you should use a different tag, and adjust with CSS to fit the styling you want. This is the most accessible solution.
You could also consider using the ARIA attribute role="presentation" on the element.
<h4 role="presentation" ng-if="voiceOver" class="keep-it-classy" ng-bind="getCurrentText()" aria-label="{{getCurrentText}}"></h4>
though I'm not sure if VoiceOver respects this for heading type elements or not!
I'm developing a desktop software application which looks for errors in web pages and can highlight them in the browser. Highlighted areas are somewhat arbitrary. They could be one word in a p tag, an entire a tag or an img.
In the past I've done this by rewriting the html and adding styled span tags around the highlighted area. The downside is that quite often the highlights can be obscured. For example where in image is in a div exactly its size with no overflow, any applied border, background etc. will be obscured.
What's the best way to approach this? Are there any good examples of this being done in popular software / webapps?
Limitations: I can't use JS (files are local and browsers often block this). I can however user the latest standards. The output doesn't have to validate, as long as it works on common modern browsers.
Since background colors and borders can't be used, I think you'll need to place something on top of the offending element or text. Perhaps you can use an absolute or fixed position <div> element with a partially transparent background.
Of course, this could get tricky with getting the coordinates. But you might be able to use the same thing you used to do with the span and add some dummy elements within it to trick it into thinking that 0,0 is right where your span element is.
JS Fiddle Link http://jsfiddle.net/Xfvpu/1/
Okay so I have a document with xhtml doctype and I use the proper br / tag
but for some reason the gap between two images renders differently in Firefox than it does every other browser.
The page is can be found at http://www.safaviehhome.com/Rugs/Area-Rugs.html
the CSS is all mixed up unfortunately so I can't explicitly post it, but the two images are within a DIV wrapper, and the images themselves are not in seperate divs. They both have image maps, and the size between the two images width only differ by around 20px.
In between the two images are two br /
tags, I tried fiddling around in Firebug but could not figure it out .. And I won't be happy until I figure this out .. it's pissing me off! :)
The difference between other browsers and Firefox is around a 10px difference .. Firefox adds extra spacing .. I'm not asking for any help specifically, just wanted to see if there is some rendering issues I'm not aware of so I can put this issue to rest.
Look in other browsers vs Firefox to see what I mean .. I would really appreciate some help I need to figure this out for my own knowledge.
You cannot rely on using <br/> for vertical spacing. You need to use styles, such as
<div style="margin-top:5px">image goes here</div>
Or even:
<img style="margin-top:5px" src="yourimg.jpg" />
In my experience browsers are sufficiently consistent if you use this approach.
Edited to add:
But (and I can't stress this strongly enough): browsers will never be entirely consistent. Designs which assume that 100% consistency is possible will fail. (If this seems harsh, try getting through one day using only your smartphone's browser. Yuck.)
While I do not know the exact reason why Firefox acts like it does, I can offer an advice. From my experience using br tags for layout are, er, not the wisest idea, since you easily lose control of the exact spacing it creates. Like in this case, where it seems that Firefox intreprets two br tags as two lines, whereas at least Opera take the first one as a line break after the map and the second one creates this empty space.
You didn't ask for a workaround, but I can't resist: take a look at br-less alternative.
When I try to create a navigation with inline-block, I get 4px to the right of each list item.
When I do it by floating each list item, it works fine.
Is there a reason the first option is applying that 4px? I have set EVERYTHING to have a margin of 0px and padding of 0px, I don't understand it. Even Firebug reports it as having 0, yet the gap is still there.
Thanks
Yes, space is by design and should be
Is there a reason for that? Yes it is. What got added is actually a word space. The same as if you'd have two lines of text. Browsers put a space between texts in separate lines so last words don't touch first words of the next line:
<p>
This is my text that's in two lines
inside my HTML source.
</p>
There would be a usual word space between lines and inside so text gets correctly displayed in browser:
This is my text that's in two lines inside my HTML source.
The same happens in your case, because your elements are inline. Your navigation elements are listed one per line in HTML source hence a word break gets added between them.
How to avoid excessive spaces between elements?
There are basically 3 approaches to mitigate this problem. All of them work on the premise to put all elements in the same line as seen by the HTML renderer:
Put all elements unspaced in a single line:
<ul>
<li>First</li><li>Second</li>...<li>Last</li>
</ul>
This one actually puts all elements in one line which may make it harder for people to manipulate these elements. If every LI would have an anchor tag inside (with a long link), this line gets too long to handle.
Comment-out line breaks:
<ul><!--
--><li>First</li><!--
--><li>Second</li><!--
...
--><li>Last</li><!--
--></ul>
Make tags break the line:
<ul
><li>First</li
><li>Second</li
...
><li>Last</li
></ul>
This one is least obtrusive to the eye but may seem confusing to beginners hence other team members (if you work in such environment) may feel tempted to put tag ends back to where they were originally (and usually are). They may feel these were broken by error.
The result of all three of them can be seen in this JSFiddle example.
Pick the one that suits you best. I usually use commenting because it's least distracting in my development editor because comments are very subtle.