Я бы выбрал первый вариант - полностью указать стиль используемых вами элементов. Но это немного сложнее, чем я думал.
Во-первых, вы должны полностью указать элемент контейнера. Затем для его потомков вы должны сказать, что они также должны использовать значения по умолчанию или наследовать от своего родителя (вплоть до контейнера). Наконец, вы должны указать внешний вид всех остальных элементов, чтобы они не были простыми.
Соответствующими API являются getComputedStyle
и CSSStyleSheet
интерфейс от DOM Level 2 Style . Вы можете использовать все значения, кроме width
и height
, которые по умолчанию должны быть auto
. Вам также необходимо загрузить таблицу стилей по умолчанию, такую как таблица стилей агента пользователя Webkit . Затем вы можете вызвать следующую функцию, чтобы создать полную таблицу стилей, которую можно вставить в документ.
Обратите внимание, что когда вы вставляете таблицу стилей в целевой документ, вам нужно будет сделать селектор контейнера как можно более конкретным, поскольку веб-страница может дать правила, которые имеют специфичность , чем ваши правила. Например, в <html id=a><head id=b><style>#a #b * {weird overrides}</style></head>
, #a #b *
имеет более высокую специфичность, чем #yourId div
. Но я думаю, что это необычно.
Примечание. По какой-то причине Chrome выдает ошибку «Не удалось загрузить ресурс» при загрузке CSS, если только он не находится в <link>
текущего документа. Поэтому вы должны включить html.css на страницу, которая также вызывает эту функцию.
// CSS 2.1 inherited prpoerties
var inheritedProperties = [
'azimuth', 'border-collapse', 'border-spacing', 'caption-side',
'color', 'cursor', 'direction', 'elevation', 'empty-cells',
'font-family', 'font-size', 'font-style', 'font-variant',
'font-weight', 'font', 'letter-spacing', 'line-height',
'list-style-image', 'list-style-position', 'list-style-type',
'list-style', 'orphans', 'pitch-range', 'pitch', 'quotes',
'richness', 'speak-header', 'speak-numeral', 'speak-punctuation',
'speak', 'speech-rate', 'stress', 'text-align', 'text-indent',
'text-transform', 'visibility', 'voice-family', 'volume',
'white-space', 'widows', 'word-spacing'];
// CSS Text Level 3 properties that inherit http://www.w3.org/TR/css3-text/
inheritedProperties.push(
'hanging-punctuation', 'line-break', 'punctuation-trim',
'text-align-last', 'text-autospace', 'text-decoration-skip',
'text-emphasis', 'text-emphasis-color', 'text-emphasis-position',
'text-emphasis-style', 'text-justify', 'text-outline',
'text-shadow', 'text-underline-position', 'text-wrap',
'white-space-collapsing', 'word-break', 'word-wrap');
/**
* Example usage:
var fullStylesheet = completeStylesheet('#container', 'html.css').map(
function(ruleInfo) {
return ruleInfo.selectorText + ' {' + ruleInfo.cssText + '}';
}).join('\n');
* @param {string} containerSelector The most specific selector you can think
* of for the container element; e.g. #container. It had better be more
* specific than any other selector that might affect the elements inside.
* @param {string=} defaultStylesheetLocation If specified, the location of the
* default stylesheet. Note that this script must be able to access that
* locatoin under same-origin policy.
* @return {Array.<{selectorText: string, cssText: string}>} rules
*/
var completeStylesheet = function(containerSelector,
defaultStylesheetLocation) {
var rules = [];
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe); // initializes contentDocument
try {
var span = iframe.contentDocument.createElement('span');
iframe.contentDocument.body.appendChild(span);
/** @type {CSSStyleDeclaration} */
var basicStyle = iframe.contentDocument.defaultView.getComputedStyle(span);
var allPropertyValues = {};
Array.prototype.forEach.call(basicStyle, function(property) {
allPropertyValues[property] = basicStyle[property];
});
// Properties whose used value differs from computed value, and that
// don't have a default value of 0, should stay at 'auto'.
allPropertyValues['width'] = allPropertyValues['height'] = 'auto';
var declarations = [];
for (var property in allPropertyValues) {
var declaration = property + ': ' + allPropertyValues[property] + ';';
declarations.push(declaration);
}
// Initial values of all properties for the container element and
// its descendants
rules.push({selectorText: containerSelector + ', ' +
containerSelector + ' *',
cssText: declarations.join(' ')});
// For descendants, some of the properties should inherit instead
// (mostly dealing with text).
rules.push({selectorText: containerSelector + ' *',
cssText: inheritedProperties.map(
function(property) {
return property + ': inherit;'
}).join(' ')});
if (defaultStylesheetLocation) {
var link = iframe.contentDocument.createElement('link');
link.rel = 'stylesheet';
link.href = defaultStylesheetLocation;
iframe.contentDocument.head.appendChild(link);
/** @type {CSSStyleSheet} */
var sheet = link.sheet;
Array.prototype.forEach.call(
sheet.cssRules,
/** @param {CSSStyleRule} cssRule */
function(cssRule) {
rules.push({
selectorText: containerSelector + ' ' + cssRule.selectorText,
cssText: cssRule.style.cssText});
});
}
return rules;
} finally {
document.body.removeChild(iframe);
}
};