?

Log in

No account? Create an account

Previous Web | Next Web

LiveJournal CSS Hacking

So, I noticed the other day that the little CSS tweaks I'd made to my LJ so it would output code, etc in an ok-looking format had stopped working. Turns out that LH have changed their HTML Cleaner so that it remvoes all class="user_class" and id="user_id" attributes in posts, which is just stoopid!. It also makes tweaking you journal's appearance a real PITA... Making this situation even more laughable is that one of LJ's features is the provision of Custom CSS functionality to let you do exactly that...! It actually makes me question why I have a paid account, I mean, this is a 'poweruser' kinda thing, it isn't (wasn't, anyway) a hack of any kind... By all means, don't allow scripts to be embedded, that makes perfect sense (and I can kinda understand not allowing the id attribute either, since that has scripting connotations too, although the id attribute is mandatory for some elements, atleast with XHTML1, which is what my journal's DOCTYPE is), but the class attribute is completely safe as its only purpose in life is as a coat-hook to hang bits of CSS-styling on... so why the cleaner removes it when its making a page 'safe', I have no idea!

Anyway, this posting started out as my test page for getting my hackarounds to work, and it demonstrates that this situation can *definitely* be hacked around.... atleast until LJ rename one of their classes that I'm using to restrict the scope of the hack to just my content. It also includes testing of a few less hacky tweaks, as I thought I'd best check they still worked too.

By the way, please don't count the number of extra <div> and <span> entities I've added to make this possible, or pay too much attention to how I'm abusing poor little <map> by using it as a pattern placeholder...!

If anyone is looking at this and thinking they'd like to 'borrow' it, my Custom CSS is included at the bottom, and before that is a table that lists the various lumps of markup that make it all work.

Since I'm making this public, I figure I'd better stick some sort of license on it... basically cause I think its actually pretty cool and I'd like to get credit for it (if there's any due!), so consider it released under the GNU Public License v2... Please feedback kudos, issues, cool modifications, etc in the comments of this post, thanks!

Styled Components

Basics

Heading 1 (matches entry title)

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6

The last three Hn tags are the same size, which is 1px bigger than the P text.

A line of text before an HR. A line of text before an HR. A line of text before an HR. A line of text before an HR.


And one after it. And one after it. And one after it. And one after it. And one after it.

A self-referential link in a paragraph.

Edits

Another paragraph which {Edit} is not formatted has been modified and a link or two added.

A footnote that the page was changed and when (multiple edits should have multiple edit timestamps added):

Edited: Feb. 24, 2015th at 2:15 PM, Feb. 25th at 5:30 PM {2} and again, Feb. 25th at 11:30 PM {3}

The {Edit} text identifies which edit made a change, so {Edit#3} implies that the changes it marks were made during the 3rd edit listed in the footnote.

Lists

  1. Ordered list entry
  2. or two
  3. multi-paragraph

    multi-paragraph

  • Unordered list entry
  • or two
  • multi-paragraph

    multi-paragraph

Blocks

A paragraph indented a bit at both sides. A paragraph indented a bit at both sides. A paragraph indented a bit at both sides. A paragraph indented a bit at both sides. A paragraph indented a bit at both sides.

Like the previous, but with a bar on the left side, like some email programs use for quoted text. Like the previous, but with a bar on the left side, like some email programs use for quoted text.

The first one again, but multiple paragraphs. The first one again, but multiple paragraphs.

The first one again, but multiple paragraphs. The first one again, but multiple paragraphs. The first one again, but multiple paragraphs. The first one again, but multiple paragraphs.

Another indented-with-bar paragraph, but with a bar on both sides, so it resembles change-bars in old-style paper documentation updates.

Quotations

A paragraph with a quote and a citation (Me).

A multi-line blockquote. A multi-line blockquote. A multi-line blockquote. A multi-line blockquote. A multi-line blockquote. A multi-line blockquote. A multi-line blockquote.

And Citation

These don't look like quotes in a graphical browser, but they are wrapped in Q tags, so should (a) show up the semantics (b) show up as Qs in, say, Lynx:

An bar-indented paragraph that is also a quote, but which doesn't get <q>'s styling applied to it, so we can use this, ie for a quote from an email and it be shown semantically in the markup.

Same as the last, but for two-bar-indented paragraphs.

And nearly forgot the first block, oops!

Code, etc

We have two inline geek-esque forms, the first refers to code we're discussing, such as a function() and uses <code> tags, while the other refers to non-code stuff, like a filename, code that we're not discussing and more nebulous stuff, such as a man(1) page, and uses <tt> tags...

We also have two geekery blocks:

this.isa (source_code_section);
requires no_input_massaging;
except (html_entities_like ('<' && '>'));
if (a_line_has_indentation)
{
    then = this.is_respected();
}

This is for terminal output.
I get this giving 88 columns on Firefox 35/Windows 7 (so Consolas gets used as 
the font), but its probably best to stick to 79 characters, as per the CGA 
standard display, as things shift a bit when zoomed, and the fallback fonts,
browsers, Operating Systems will have different metrics.
         1         2         3         4         5         6         7         8        
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678

We can apply some text attributes like bold and italic using, ie <em>.
For others (underline, coloured and bright coloured) we use <span>s... 

Issues

  • You can NEVER nest four <span>s... three is fine, but four matches the 'edited' footnote... I don't think this should ever really be an issue, but its something to be aware of
  • The 'edited' footnote has a small issue, in that the shrunkenness applies to a <span> within a <p>, not to the <p> itself, so it doesn't shrink the block. This isn't super-obvious, it just means that you can see the grey background of the normal 'editted' <span> as a line above the 'Edited: ' text... which is annoying from a technical perspective, but doesn't look that bad...
  • Poor old <map> really is being abused...
  • Speaking of which, if you want the HTML to validate, you need to use a valid proper-form of <map> that includes an id attribute; I've used <map id="mymap1">, <map id="mymap2">, etc...

Notes

  • The Theme uses px for every size I've looked at, so the tweaking CSS does the same.
  • Its not easy to check that all this hackery is valid XHTML because the LJ stuff that surrounds your entry-content is piss-poor....

    If you run a page through W3's Validator, you'll see that LJ is super bad... Validating this test post, I'm getting, like, 200+ errors back; my entry's actual content starts around line 710-ish, and only raises errors regarding <map> not having the mandator id attribute specified, which is also LJ's fault, since its stripping the ids from my HTML.


Markup

{Edit} <span><span><span><span>{Edit}</span></span></span></span>
deleted <del>deleted</del>
inserted <ins>inserted</ins>
Editted: <span><span><span><span><span>Editted: </span></span></span></span></span>
  • List

    Entry wth multiple paragraphs

<ul><li><div><p>Multi-paragraph</p><p>List entry</p></div></li></ul>
Indented paragraph
<map id="m"><div><map id="n"><div>Indented paragraph</div></map>
</div></mapv>
Left-bar paragraph
<map id="m"><div><div><map id="n"><div>Left-bar paragraph</div>
</map></div></div></map>
Both-bar paragraph
<map id="m"><div><div><div><map id="n"><div>Both-bar paragraph
</div></map></div></div></div></map>
Paragraph quote (Cite) Paragraph <q>quote</q> (<cite>Cite</cite>)
Blockquote

Cite

<blockquote>Blockquote</blockquote><p><cite>Cite</cite></p>
Indented quote
<map id="m"><div><map id="n"><div>Indented quote</div></map></div></map>
Left-bar quote
<map id="m"><div><div><map id="n"><div>Left-bar quote</div></map></div>
</div></map>
Both-bar quote
<map id="m"><div><div><div><map id="n"><div>Both-bar quote</div>
</map></div></div></div></map>
code being discussed <code>code being discussed</code>
files, etc <tt>files, etc</tt>
code
block
<pre>code
block</pre>
output
block
<div><pre>output
block</pre><div>

The CSS

/* 
style "Spider Purple (Faerieality)
extends "Spider Purple"

Note: The theme is using px, so we do likewise 
*/
/*
Basics
----------
*/
div.post-asset div.asset-body {
/*
  Its nicer to have text justified when you have a solid block of colour down 
  the right side; the *wonky* of 'left' is too jarring against the 
  ruler-straightness!
*/
  text-align : justify;
}

div.post-asset div.asset-body h1 {
/*
  Taken from page-header2, so it matches the entry header
*/
  font-size : 22px;
  font-weight : bold;
}
div.post-asset div.asset-body h2 {
  font-size : 18px;
  font-weight : bold;
}
div.post-asset div.asset-body h3 {
  font-size : 16px;
  font-weight : bold;
}
div.post-asset div.asset-body h4 {
  font-size : 14px;
  font-weight : bold;
}
div.post-asset div.asset-body h5 {
  font-size : 14px;
  font-weight : normal;
}
div.post-asset div.asset-body h6 {
  font-size : 14px;
  font-weight : normal;
  font-style : italic;
}
div.post-asset div.asset-body tt {
  font-family : "Consolas", "Courier New", "Courier", monospace;
}
div.post-asset div.asset-body hr {
  width : 50%;
  height : 1px;
  color : #7B5191;
  border : none;
  background-color : #7B5191;
  height : 4px;
  margin-left : auto;
  margin-right : auto;
  margin-bottom : 9px;
}

div.post-asset div.asset-body a {
  color : #7B5191;
}

div.post-asset div.asset-body td {
  vertical-align : top;
}

/*
Edits
-------
*/
div.post-asset div.asset-body span>span>span>span {
/*
  For the {Edit} marker 
*/
  color : #a070c0;
  background-color : #e8e8e8;
}

div.post-asset div.asset-body span>span>span>span>span {
/*
  This one is for the 'Edited: timestamp' footnote
*/
  background-color : white;
  color : #a070c0;
  font-size : smaller;
}

div.post-asset div.asset-body del {
/*
  Red strike-through for erased, so its can still be seen... 
  Retractions not redactions!
*/
  font-style : normal;
  text-decoration : line-through;
  color : red;
  background-color : #ffe0ff;
}

div.post-asset div.asset-body ins {
/*
  Only fair that adds show up too
*/
  font-style : normal;
  text-decoration : none ! important;
  color : green;
  background-color : #e8ffdc;
}

/* 
Lists 
-----
*/
div.post-asset div.asset-body ul,
div.post-asset div.asset-body ol {
  padding-left : 14px;
  padding-right :22px;
  margin : 0 20px
}

div.post-asset div.asset-body li {
/*
  This evens up the indents on a list... breaking up the justified-ness 
*/
  text-align : justify;
  padding : 0 8px 0.5em;
}

div.post-asset div.asset-body li p {
/*
  This makes P-in-LIs not take up excess space... means we can have 
  multi-line LIs by doing LI-DIV-P1-P2
*/
  margin-bottom : 0;
}

/*
Blocks
------
The thinking with these is to escape user-selectorless-hell... these are 
various blocks of "normal" (ie, not code or quoted) text, so we have to work 
on the assumption that some box-model nesting is possible.... if we assume DIV 
container
--> DIV column
--> --> DIV row
--> --> --> DIV leeway
is the worst this will get, we need 5 DIVs for the
lowest-level block... no-one said this was gonna be pretty :-/
*/

div.post-asset div.asset-body>div>div>div>div>div>map>div {
/*
  Indent a block of text a bit.
  This is for a normal paragraph, not one squashed by the userpic.
  This is *specifically* for use where lines need to line up with the text in a 
  1st-level LI (ie after an image that gets the whole post width)
*/
  margin-left : 20px;
  margin-right : 20px;
  padding-left : 22px;
  padding-right : 22px;
}

div.post-asset div.asset-body>div>div>div>div>div>div>map>div {
/*
  Specialism of the above... adds a left border, like some email programs do
  for quoted message text
*/
  margin-left : 15px;
  margin-right : 20px;
  padding-left : 22px;
  padding-right : 22px;
  border-left : 5px solid #7B5191;
}

div.post-asset div.asset-body>div>div>div>div>div>div>div>map>div {
/*
  Specialism of the above... adds a right border too, like change-bars in 
  old-style paper documentation updates
*/
  margin-left : 15px;
  margin-right : 15px;
  padding-left : 22px;
  padding-right : 22px;
  border-left : 5px solid #7B5191;
  border-right : 5px solid #7B5191;
}

div.post-asset div.asset-body>div>div>div>div>div>map>div>p>span>q {
/* 
  Lets us set an indented block as a quote, without having quote styling 
  applied. The SPAN should prevent normal usage of a Q from being broken... 
  just don't find a need for a Q in a SPAN!
*/
  quotes : none;
  font-style : normal;
}

div.post-asset div.asset-body>div>div>div>div>div>div>map>div>p>span>q {
/* 
  Lets us set a left-bar-block as a quote, without having quote styling 
  applied. The SPAN should prevent normal usage of a Q from being broken... 
  just don't find a need for a Q in a SPAN!
*/
  quotes : none;
  font-style : normal;
}

div.post-asset div.asset-body>div>div>div>div>div>div>div>map>div>p>span>q {
/*
  Lets us set a two-bar-block as a quote, without having quote styling 
  applied. The SPAN should prevent normal usage of a Q from being broken...
  just don't find a need for a Q in a SPAN!
*/
  quotes : none;
  font-style : normal;
}

/*
Quotations
----------
2 forms of quotation are supported:
1) an inline quote, ie 
[ This is a sentence containing "...the damnation of saints" , as spake by 
(cite) as he struggled with LJ styling. ]
2) a statement quote, ie 
[
"To say sod it, I can hack this.....(!) or to hunt down the muppet who made 
LJ's HTML scrubber eat class, name and id attributes and make them eat every 
last rejected one, that is the question."
------> (cite) 
]
Originally this was a big PIA, as I was planning to use 'blockquote' for the 
block-indented-quotes, below, but since those are now done purely with DIVs 
and Qs, it can be used more correctly :-)

We also have 'cite' rules for the two 'q' types.... the 1st cite rule is nice 
and easy... the 2nd is a bit more challenging...
*/

div.post-asset div.asset-body p q {
  font-style : italic;
}

div.post-asset div.asset-body p q+cite {
  font-style : normal;
}

div.post-asset div.asset-body blockquote {
  font-style : italic;
  text-align : center;
  margin-left : 42px;
  margin-right : 42px;
  padding-left : 0;
  padding-right : 0;
/*
  Spider Purple's 'screen.css' includes a big quotemark that doesn't now work 
  right, so we have to override this:
    background: url(blockquote.gif?v=1) no-repeat 12px 3px;
  with this:
*/
background: none;
}

div.post-asset div.asset-body blockquote+p>cite {
  text-align : right;
  font-style : normal;
  margin-left : 20px;
  margin-right : 20px;
  display : block;
/*
  ^-- is a bit of a hack, but there's no easy way I can think of to apply 
  style to something that is the parent of the element of specificity
*/
}
div.post-asset div.asset-body blockquote+p>cite:before {
/* 
  Give blockquote citations some brackets 
*/
  content : "(";
}
div.post-asset div.asset-body blockquote+p>cite:after {
/* 
  Give blockquote citations some brackets 
*/
  content : ")";
}

/*
Code, etc
---------
Representation of code, both inline and as a block, program output (block 
only) and other (inline-only) geeky bits.
*/

div.post-asset div.asset-body>pre {
/*
  A block of code
*/
  margin-left : 40px;
  margin-right : 40px;
  padding-left : 2px;
  padding-right : 2px;
  border : 1px solid #7B5191;
  background-color : #d8c7dc;
  font-family : "Consolas", "Courier New", "Courier", monospace;
}

div.post-asset div.asset-body code {
/* 
  A fragment of code inline in a P 
*/
  padding-left : 2px;
  padding-right : 2px;
  border : none;
  background-color : #d8c7dc;
  font-family : "Consolas", "Courier New", "Courier", monospace;
}

div.post-asset div.asset-body>div>pre {
/* 
  A block of terminal output 
*/
  margin-left : 40px;
  margin-right : 40px;
  padding-left : 2px;
  padding-right : 2px;
  color : #c0c0c0;
  border : 1px solid #7B5191;
  background-color : black;
  font-family : "Consolas", "Courier New", "Courier", monospace;
}