User generated custom css
and then using dom:loaded with prototype
Awww, don't do that! That won't work when JavaScript is turned off.
Approach 1: Static stylesheet, dynamic values in document head
For the sake of not having to work with a dynamically created style sheet, have a separate, static CSS file with all the definitions that won't change.
<link rel="stylesheet" href="styles/static.css" type="text/css">
<!-- Or whatever you name it -->
All the definitions that will change, you could put into the head
of the HTML document, fetching the user-changeable values from a database.
<style type="text/css">
.classname { font-size: (fontsize); } <-- Insert dynamic value here
.classname { color: (color); } <-- Insert dynamic value here
....
<style>
that way, the majority of the CSS stays in static, cacheable files, while the dynamic part won't cause another HTTP request.
Approach 2: Dynamic stylesheet
If you have a lot of dynamically changing values, put the entire style sheet into a script file and output it, replacing placeholders with the values from the database.
The downside to this is that to force the browser to reload the style sheet on changes, you'll have to work with a version approach stylesheet.css?version=400
which is pretty complex to do, but can sometimes be more desirable than littering the head
section with CSS.
You decide which approach suits your situation better. I find myself choosing the first one most often.
How to create custom CSS on the fly based on account settings in a Django site?
I've used option #2 with success. There are 2 decent ways of updating the generated static files that I know of:
Use a version querystring like /special_path.css?v=11452354234 where the v parameter is generated from a database field, key in memcached, or some other persistent file. Version gets updated by admin, or for development you would just make the generation not save if the parameter was something special like v=-1. You'll need a process to clean up the old generations after some time.
Don't use a version querystring, but have it look first for the generated file, if it can't find it, it generates it. You can create a cron job or WSGI app that looks for filesystem changes for development, and have a hook from your admin panel that deletes generations after an update. Here's an example of the monitoring, which you would have to convert to be specific to your generations and not to Django. http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode#Monitoring%5FFor%5FCode%5FChanges
What is the best way to handle user generated html content that will be viewed by the public?
That's an entirely reasonable approach. For typical applications it will be entirely sufficient.
The trickiest part of white-listing raw HTML is the style
attribute and embed
/object
. There are legitimate reasons why someone might want to put CSS styles into an otherwise untrusted block of formatted text, or say, an embedded YouTube video. This issue comes up most commonly with feeds. You can't trust the arbitrary block of text contained within a feed entry, but you don't want to strip out, e.g., syntax highlighting CSS or flash video, because that would fundamentally change the content and potentially confuse anyone reading it. Because CSS can contain dangerous things like behaviors in IE, you may have to parse the CSS if you decide to allow the style
attribute to stay in. And with embed
/object
you may need to white-list hostnames.
Addenda:
In worst case scenarios, HTML escaping everything in sight can lead to a very poor user experience. It's much better to use something like one of the HTML5 parsers to go through the DOM with your whitelist. This is much more flexible in terms of how you present the sanitized output to your users. You can even do things like:
<div class="sanitized">
<div class="notice">
This was sanitized for security reasons.
</div>
<div class="raw"><pre>
<script>alert("XSS!");</script>
</pre></div>
</div>
Then hide the .raw
stuff with CSS, and use jQuery to bind a click handler to the .sanitized
div
that toggles between .raw
and .notice
:
CSS:
.raw {
display: none;
}
jQuery:
$('.sanitized').click(function() {
$(this).find('.notice').toggle();
$(this).find('.sanitized').toggle();
});
Prepend custom css to generated CSS files
You can solve it with jQuery:
function isIE() {
return (navigator.userAgent.toLowerCase().indexOf('msie ') != -1) || (!!navigator.userAgent.match(/Trident.*rv[:]*11\./));
}
$(function() {
if (isIE()) {
//merging all the content in your generated styles
var styles = $("style").text();
//getting rid of the many unneeded styles
$("style").remove();
//Putting back all the styles into your document
$("head").append("<style>" + styles + "</style>");
}
});
The idea is to merge the styles into a single text, remove all the styles and then create a single style tag instead of them. You need this only for IE, so I have added a function with which you can check whether it is Internet Explorer and if so, then merge the styles.
Where is custom.css in the generated html file from nbconvert?
The <link rel="stylesheet" href="custom.css">
effectively causes customized CSS styling rules to be included if the file custom.css
exists in the same directory.
In case you want some customized CSS styling rules for displaying the generated html. You can add a file custom.css
with those rules, in the same directory as the html file.
This is not a mandatory requirement. It is fine to not include such a file if you don't want any customized styling rules. The default CSS rules in generated HTML file will still work.
applying styles to static site html and user generated html content
Using an iframe is the way to go.
Here's some examples of how to communicate with it and access it's content.
The iframe content can call a function in the parent like this:
parent.yourFunction()
The parent can call a function in the iframe like this:
document.getElementById('iframeid').contentWindow.yourFunction();
The parent can access the iframe's html like this:
document.getElementById('iframeid').innerHTML() = "<html><body><div>some content</div></body></html>";
Not quite what you were hoping but it's the only way to have css only apply to part of a page.
keep user-generated content from breaking layout?
Maybe overkill, but HTML
Tidy
could help if you can use it.Use a WYSIWYG like
TinyMCE
or CKEditor that has built in cleanup methods.
Robert Koritnik's suggestion to use markdown seems brilliant, especially considering that you only allow a few harmless formatting tags.
I don't think there's anything you can do with CSS to stop layouts from breaking due to open HTML tags, so I would probably forget that idea.
Related Topics
Convert Internal Stylesheet to Inline CSS
Css3 Grid Layouts: New Row After Specific Element - Possible
Purgecss Whitelist Patterns with Tailwindcss
CSS Icon Using :Before Keep Text from Wrapping Under
React Table with Static Header on Browser Scroll
Why Is It Impossible to Change Content in CSS
How to Align a Div to The Top of Its Parent But Keeping Its Inline-Block Behaviour
Print Page Count with Total Number of Pages Using CSS
How to Fix Inconsistent Textarea Bottom Margin in Firefox and Chrome
Typo3 Show Content from Subpages Inlcuding CSS Classes
IE8 Renders Font Weights Randomly
Setting CSS Style Attributes with Thymeleaf
Line Numbers Every Nth Line with CSS Counters
Weird Webkit Issue with Position: Fixed
Can Relative Paths Be Used for @Font-Face Src
Xpages: Ibm Oneui VS. Bootstrap