Feature Request: Pass through table styling when compiling to KF8/Mobi

Table styling (alignment, borders, and column widths are my concerns) specified in Scrivener 3 are maintained in the compiled output except for ebooks, even though HTML allows for such settings.This means that every table must have identical styling. Perhaps there is a way to override the styling on an individual table or table element basis, but if so I haven’t been able to do so with CSS, HTML classes, and Scrivener styles, so if there is a way to do so that works let me know!

The project I’m working on does have some simple tables, but the problem is with what would be with a Descriptions List (dl) HTML tag in HTML or with a hanging indent and a tab stop at the left margin in traditional documents. It looks like this in Scrivener and works fine for compile to RTF, PDF, and I would guess other outputs but doesn’t work at all for ebooks because there are no tab stops:

To enter the text I type the left text of a line, a tab, and then type in the right text which conveniently wraps to additional lines at the correct position.
So I thought I could just put the text in a table with the table settings:

left and top aligned with no border, skipping the header row (empty first line) since there is no way to specify zero header rows. Then it looks like this in Scrivener:

This compiles to RTF or PDF correctly but the styling is ignored when compiled to KF8/Mobi. Borders appear and the alignment is wrong unless I add to the CSS, which then affects the formatting of the real tables. So I’m basically at an impasse unless I edit the generated HTML, which I don’t want to do for maintenance reasons.

There are a few ways you could get a result that makes it possible to avoid editing tables in post-compile. One method will work better if the table can be in its own binder item—and hence able to use a custom Layout that sets up an environment that we can later make use of in CSS. It’s a good way to get a lot of control for “free”, but if you really need the table to be in the middle of a chunk of text and it would be unwieldy to break the section up for the sake of a table, I’ll describe another method as well.

Using Section Layouts

Since we are in essence talking about a class of table (even if there is only one like this, it can be useful to think of it as such), we could create a dedicated Section Type for borderless tables, and use that to store them in the binder, and ultimately to apply special formatting that only applies to them.

  1. Go into Project ▸ Project Settings... in the Section Types pane, and click the + button to create a new Type. For the sake of this example, I’ll call it “Instructions” (I’m guessing at a good semantic name here—use whatever works best). Click OK.
  2. Now go into the draft and break this table out into its own section if necessary.
  3. In the Metadata pane of the Inspector, set the table item to use the new “Instructions” type.

Creating a Compile Layout

Next we need to create a Layout that handles tables of this class:

  1. Load up File ▸ Compile... and edit your Format.
  2. In the Section Layouts pane, create a new layout called “Borderless Table”, probably based off of the basic “Section Text” layout.
  3. Click on the “Settings” tab, and for the CSS class name, type in “borderless-table”.
  4. Now visit the Separators compile format pane, as most likely you will not want the table to break to a new section. Override the defaults for this Layout and set all separators to “Single Return” (unless of course you do want it in its own ToC section).
  5. Save and return to the compile overview screen. Make sure to assign your “Instructions” document type to the new “Borderless Table” layout.

Now let’s test the settings. I prefer to use plain HTML at this phase, because it is easier to load the ePub source files in a text editor and Firefox Developer Edition (for tweaking styles and such) and examine them directly, rather than loading the ePub into Calibre or whatever. To do so, go back into the Format designer and hold down the Option key. The Test... button in the lower left will become Test HTML.... Give it a folder name and click Save.

Find the .xhtml file that contains the table, and take a look at it in your editor. You should see that the entire table is now surrounded by a <div class=“borderless-table”> element. Perfect, that’s all we need to give CSS a hook into modifying the look of this table directly.

Setting up the CSS

So let’s do that now. Go into the CSS compile format pane, and make sure “Append custom CSS Stylesheet” is selected. The left column is editable. This is where you can set your own CSS. Add something like the following:

.borderless-table table, .borderless-table td, .borderless-table th { border: none; }
.borderless-table th { font-weight: normal; }
.borderless-table table { width: 100%; }

You get the idea. Run another test compile and preview the settings.

Note here I am removing the vanilla formatting from the header row (th), making it look like a normal row, rather than inserting nothing in the original table. I’m not sure which is actually best to be honest. Having a header row that isn’t a header row and looks normal, or having a header row with no content in it—neither strikes me as semantically better, but personally I’d rather have a normal looking table in the editor.

Using Embedded HTML

So what if you do not want the table in its own section type? You can achieve precisely the same result above with a little Style usage:

Adding HTML to the Editor

We’ll need to add HTML to the editor itself to wrap the tables in a classed div. For the sake of simplicity, we’ll use the same class name as above, meaning we could in fact even use both methods on different tables as desired, since the end result will be identical at the HTML level once we compile—we’re just using different approaches for getting that HTML around the table.

  1. Locate the table you want to remove the borders from in the editor, and above and below it, type in the “<div class=‘borderless-table’>” and “</div>” yourself.
  2. Select the first HTML line and give it a formatting touch or two. I prefer using a monospace font and maybe a colour like red to help enunciate the intention of the text.
  3. With the line still selected, use the Format ▸ Style ▸ New Style from Selection... menu command. Name the style “Raw HTML Block” (the name matters, as the Ebook compile format has a matching style set up for this purpose), saving the paragraph and character attributes, and whatever other options you prefer.
  4. Of course, select the second HTML line below the table and apply this new style to it.

Setting Up an HTML Pass-Thru Style

Next step is to tell the compiler what we want to do with the style. As noted above, if you’re using the stock Ebook compile format then you can skip this step because it comes configured with a “Raw HTML Block” that will work for what we want out of the box. But if you are creating your own Format from scratch, use these steps to set up the style:

  1. Open File ▸ Compile... and edit the Format.
  2. In the Styles compile format pane, click the + button and select our new “Raw HTML Block” style.
  3. Simply tick the Treat as raw markup option on the right.

While you’re here, take note of the other options. You wouldn’t be able to use this approach for tables, given how Styles work within them rather than upon them, but for other things, you can avoid a bunch of this wiring by adding HTML directly to styled elements. Another thing worth noting here is the Delete text of this style checkbox. You don’t want that for this example—but say this project is also used to create a PDF, you wouldn’t want HTML instructions in the PDF. That checkbox can be used in the Format you use to create the PDF, to strip out all HTML codes.

Testing the Settings

Okay at this point we have everything we need. If you’re working off of the prior example with a different table, then you could run a test compile right now. Otherwise, you would need to implement the CSS for the .borderless-table class, as described in the previous section.

And of course, now that you know how to inject raw HTML, you could even construct the entire table yourself in HTML, thus avoiding the limitation of needing a header row. The method works equally well for larger constructs, as well as one-liners.

Definition Lists

As a postscript, you mentioned wishing you had access to HTML definition lists. A neat trick to be aware of is that our Treat as raw markup style in actual fact merely tells the compiler to not mess with your text in any fashion and to insert it directly into the intermediate MultiMarkdown document that it converts the RTF into. This temporary MMD document is then used to generate the HTML5 content for the eBook. In other words, this isn’t just a method for inserting raw HTML—that happens as a side-effect of how raw HTML is handled in a MultiMarkdown file—you can insert raw MultiMarkdown too!

Definition term
: Definition body text.

: Continuation...

Next term
: And so on...

Slap the style on top of that, and you’ll get a clean DL on output.

Thanks! That does it. I think that for me the “Raw HTML” solution is just what I want. I hadn’t realized that was possible – I had thought that the “treat as raw markup” box only applied to MultiMarkDown. The documentation certainly implies as much.

Great! Glad that works.

Hmm, are you referring to the description provided on page 610, under §24.5.3? The one practical example I gave is HTML specific. In fact I did just edit that entry a bit after writing the above, as I noted it didn’t refer to the ability to use MMD with ePub3/KF8 as well as HTML.

Let’s just say I’m getting confused. I just don’t think of HTML tags as “markup”, probably my bad judgment. After some rereading I now see that Preserve Formatting (section 15.4.6) which I though no longer worked (I used it for blocks of monospaced code now handled by the Code style), it looks like it passes through raw HTML which it didn’t do before in Scrivener 2. And, indeed, that solves the problem as well, but using a style is certainly better.

I do think that the way 24.5.3 was written doesn’t help in understanding. Starting off the example with a counter example of “>” becoming &gt doesn’t help. Supposing you just said

HTML definitely falls under the umbrella of “markup”. HyperText Markup Language.

I’ll see about simplifying the example a bit though, you are right there is no need to start with an example that wouldn’t be useful to ever use anyway.

(face slap) of course! I’ve just stopped thinking of what the letters mean!