Forum How do I...?

Screenplay dialog formatting

rnkn
I've managed to approximate the formatting of screenplay dialog, specifically when dialog is broken at a page, the text "(MORE)" is rendered at the bottom of the first page, the character name is repeated on the next page with " (CONT'D)" appended to it, and the remaining dialog comes after that. I've attached a picture to make this a lot clearer.

I find my solution rather sloppy: I've used tables, but not table-header-group, rather setting the caption content to be the "character" attribute of the table, with " (CONT'D)" appended; then I've used "dialog-start" class to set a named string "more-dialog" to "(MORE)" and reset the same string to "" at "dialog-end" class. It seems to work, but it's hardly elegant.

The HTML (assume auto page break comes within "td.dialog"):

<table class="dialog" character="BOBBY WOMACK">
<caption />
<tr><td class="dialog-start"></td></tr>
<tr><td class="character">BOBBY WOMACK</td></tr>
<tr><td class="dialog">Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec hendrerit tempor tellus.</td></tr>
<tr><td class="dialog-end"></td></tr>
</table>


And the CSS:

@page screenplay {
    @bottom-left {
        font-family: 'Courier','Courier New';
        font-size: 12pt;
        content: string(more-dialog, last);
        margin-left: 2in;
        vertical-align: top;
    }
}
table.dialog {
    margin-top: 1em;
    margin-bottom: 1em;
    margin-left: 1in;
    border-spacing: 0px;
    width: 4in;
    caption-side: top;
    caption-page: following;
    string-set: character attr(character);
}
td {
    display: block;
}
td.character {
    margin-left: 1in;
    page-break-after: avoid;
}
td.dialog {
    width: 3.5in;
    orphans: 2;
    widows: 2;
}
caption {
    margin-left: 1in;
    text-align: left;
    content: string(character, last)" (CONT'D)";
}
td.dialog-start {
    height: 0in;
    string-set: more-dialog "(MORE)";
}
td.dialog-end {
    height: 0in;
    string-set: more-dialog "";
}


What I'd really like to do is dispense with the "dialog-start" and "dialog-end" classes and instead just set the "more-dialog" string with "table.dialog:before" and reset it with "table.dialog:after" but this does not appear to work, unless I'm doing it wrong?

Otherwise, is there a better way to achieve the same result, maybe without tables?
  1. IMG_0488.JPG110.4 kB
    BOBBY DAREN is speaking a lot of Latin
mikeday
Have you tried something like this:
table.dialog::before {
    display: table-row;
    content: "";
    string-set: ...
rnkn
In the words of Leonard Cohen, hallelujah. Thanks Mike.

To sate my curiosity, is it that string-set will not work on elements with no or a "none" display property?
mikeday
Right, technically the pseudo-element won't even be created unless it has some content, so none of the other properties will have any effect.
rnkn
Many thanks Mike, everything works a treat. If I may entreat one more question...

Currently the "(MORE)" string in the footer sits vertically aligned to the top of the footer, which appears to be a fixed height and thus not always hugging the last bit of page text. If I were to wish this "(MORE)" text to sit flush up against the lowest bit of page text, regardless of where that page text were to end, would there be a way to achieve this?

I had thought this would be a simple case of creating a div, giving that div a "height: auto;" property, and using "flow: static(div);" but it wasn't to be. I also tried playing around with footnotes, but this didn't prove fruitful either.

Ideas?
mikeday
Could you use a table footer for the (MORE), eg. a <tfoot> element?
rnkn
It does not appear this is possible. I've seen in other threads it's apparently a limitation of CSS that the <tfoot> cannot be changed across pages...? Even if I could specify that <tfoot> only displayed on prior pages when a table breaks across a page would suffice...

Setting the string is no problem, but resetting it (so it doesn't appear everywhere) is the issue. I've tried the following:

table.dialog:after {
    display: table-row;
    content: "";
    string-set: more-dialog "";
}
table.dialog tbody:after {
    [...]
}
tr.dialog-end {
    [...]
}


and no dice...
mikeday
Hmm, good point. How about another page caption, with caption-page: following and caption-side: bottom?

Edit: wait, I got mixed up, you need it to appear on every page except the last, not the first. Maybe we need a new caption-page setting for that.

Edited by mikeday

rnkn
Yeah therein lies the rub. I've tried inserting the <caption class="more-dialog"> after the <tbody> element, which surprisingly works despite being against the W3C rules (I think), but the paint order seems to make it impossible to change the caption content string midway through rendering the table.

It does appear that the only way to achieve this would be with something like a "prince-caption-page: all-except-last" property. Oh well, until such a time the @bottom-left page margin will suffice.

P.S. I'm quite impressed that Prince will permit me not only multiple table captions, but that these may have separate classes. Pretty cool.