javascript 将文本拆分为页面并单独呈现 (HTML5)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12202324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Split text into pages and present separately (HTML5)
提问by David Mulder
Let's say we have a long text like Romeo & Juliet and we want to present this in a simple ereader (no animations, only pages and custom font-size). What approaches exist to get this?
假设我们有一个像罗密欧与朱丽叶这样的长文本,我们想在一个简单的电子阅读器中呈现它(没有动画,只有页面和自定义字体大小)。有什么方法可以得到这个?
What I have come up with so far:
到目前为止我想出了什么:
- Using css3 columns it would be possible to load the entire text into memory styling it in such a way that a single column takes the size of an entire page. Doing this turned out to be extremely hard to control and requires the entire text to be loaded into memory.
- Using css3 regions (not supported in any major browser) would constitute the same basic concept as the previous solution, with the major difference that it wouldn't be as hard to control (as every 'column' is a self contained element).
- Drawing the text on a canvas would allow you to know exactly where the text ends and thus draw the next page based on that. One of the advantages is that you only need to load all the text up to the current page (still bad, but better). The disadvantage is that the text can't be interacted with (Like selecting the text).
- Place every single word inside an element and give every element a unique id (or keep a logical reference in javascript), next use
document.elementFromPoint
to find the element(word) which is the last on the page and show the next page onward from that word. Despite this being the only one which seems actually realistic to me, the overhead generated by this has to be immense.
- 使用 css3 列,可以将整个文本加载到内存中,以这样一种方式,即单个列占据整个页面的大小。事实证明,这样做非常难以控制,并且需要将整个文本加载到内存中。
- 使用 css3 区域(不受任何主要浏览器支持)将构成与先前解决方案相同的基本概念,主要区别在于它不会那么难控制(因为每个“列”都是一个自包含元素)。
- 在画布上绘制文本可以让您确切地知道文本结束的位置,从而基于此绘制下一页。优点之一是您只需要将所有文本加载到当前页面(仍然很糟糕,但更好)。缺点是无法与文本进行交互(例如选择文本)。
- 将每个单词放在一个元素中,并给每个元素一个唯一的 id(或在 javascript 中保留一个逻辑引用),接下来用于
document.elementFromPoint
查找页面上的最后一个元素(单词)并从该单词开始显示下一页。尽管这是唯一一个对我来说似乎真正现实的方法,但由此产生的开销必须是巨大的。
Yet none of those seems to be acceptable (first didn't give enough control to even get it to work, second isn't supported yet, third is hard and without text selection and fourth gives a ridiculous overhead), so any good approaches I haven't thought of yet, or ways to solve one or more disadvantages of the mentioned methods (yes, I am aware this is a fairly open question, but the more open it is, the higher the chance of producing any relevant answers)?
然而,这些似乎都不是可以接受的(第一个没有给予足够的控制来让它工作,第二个还不支持,第三个很难并且没有文本选择,第四个给出了一个荒谬的开销),所以任何好的方法我还没有想到,或解决上述方法的一个或多个缺点的方法(是的,我知道这是一个相当开放的问题,但它越开放,产生任何相关答案的机会就越大)?
采纳答案by Eric
See my answerto Wrap text every 2500 characters in a for pagination using PHP or javascript. I ended up with http://jsfiddle.net/Eric/WTPzn/show
见我的答案来总结每2500个字符的文本在使用PHP或JavaScript分页。我最终得到了http://jsfiddle.net/Eric/WTPzn/show
Quoting the original post:
引用原帖:
Just set your HTML to:
<div id="target">...</div>
Add some css for pages:
#target { white-space: pre-wrap; /* respect line breaks */ } .individualPage { border: 1px solid black; padding: 5px; }
And then use the following code:
var contentBox = $('#target'); //get the text as an array of word-like things var words = contentBox.text().split(' '); function paginate() { //create a div to build the pages in var newPage = $('<div class="individualPage" />'); contentBox.empty().append(newPage); //start off with no page text var pageText = null; for(var i = 0; i < words.length; i++) { //add the next word to the pageText var betterPageText = pageText ? pageText + ' ' + words[i] : words[i]; newPage.text(betterPageText); //Check if the page is too long if(newPage.height() > $(window).height()) { //revert the text newPage.text(pageText); //and insert a copy of the page at the start of the document newPage.clone().insertBefore(newPage); //start a new page pageText = null; } else { //this longer text still fits pageText = betterPageText; } } } $(window).resize(paginate).resize();
只需将您的 HTML 设置为:
<div id="target">...</div>
为页面添加一些 css:
#target { white-space: pre-wrap; /* respect line breaks */ } .individualPage { border: 1px solid black; padding: 5px; }
然后使用以下代码:
var contentBox = $('#target'); //get the text as an array of word-like things var words = contentBox.text().split(' '); function paginate() { //create a div to build the pages in var newPage = $('<div class="individualPage" />'); contentBox.empty().append(newPage); //start off with no page text var pageText = null; for(var i = 0; i < words.length; i++) { //add the next word to the pageText var betterPageText = pageText ? pageText + ' ' + words[i] : words[i]; newPage.text(betterPageText); //Check if the page is too long if(newPage.height() > $(window).height()) { //revert the text newPage.text(pageText); //and insert a copy of the page at the start of the document newPage.clone().insertBefore(newPage); //start a new page pageText = null; } else { //this longer text still fits pageText = betterPageText; } } } $(window).resize(paginate).resize();
回答by markE
SVG might be a good fit for your text pagination
SVG 可能非常适合您的文本分页
SVG text is actually text -- unlike canvas which displays just a picture of text.
SVG text is readable, selectable, searchable.
SVG text does not auto-wrap natively, but this is easily remedied using javascript.
Flexible page sizes are possible because page formatting is done in javascript.
Pagination does not rely on browser dependent formatting.
Text downloads are small and efficient. Only the text for the current page needs to be downloaded.
SVG 文本实际上是文本——与仅显示文本图片的画布不同。
SVG 文本可读、可选择、可搜索。
SVG 文本本身不会自动换行,但使用 javascript 可以轻松解决此问题。
灵活的页面大小是可能的,因为页面格式化是在 javascript 中完成的。
分页不依赖于浏览器相关格式。
文本下载小而高效。只需要下载当前页面的文本。
Here are the details of how SVG pagination can be done and a Demo:
以下是如何完成 SVG 分页的详细信息和演示:
http://jsfiddle.net/m1erickson/Lf4Vt/
http://jsfiddle.net/m1erickson/Lf4Vt/
Part 1: Efficiently fetch about a page worth of words from a database on the server
第 1 部分:从服务器上的数据库中有效地获取大约一页的单词
Store the entire text in a database with 1 word per row.
将整个文本存储在数据库中,每行 1 个单词。
Each row (word) is sequentially indexed by the word's order (word#1 has index==1, word#2 has index==2, etc).
每行(单词)按单词的顺序依次索引(单词#1 的索引==1,单词#2 的索引==2,等等)。
For example this would fetch the entire text in proper word order:
例如,这将以正确的词序获取整个文本:
// select the entire text of Romeo and Juliet
// “order by wordIndex” causes the words to be in proper order
Select word from RomeoAndJuliet order by wordIndex
If you assume any page has contains about 250 words when formatted, then this database query will fetch the first 250 words of text for page#1
如果您假设任何页面在格式化时包含大约 250 个单词,那么此数据库查询将获取 page#1 文本的前 250 个单词
// select the first 250 words for page#1
Select top 250 word from RomeoAndJuliet order by wordIndex
Now the good part!
现在是好的部分!
Let's say page#1 used 212 words after formatting. Then when you're ready to process page#2 you can fetch 250 more words starting at word#213. This results in quick and efficient data fetches.
假设第 1 页在格式化后使用了 212 个单词。然后,当您准备好处理 page#2 时,您可以从 word#213 开始获取 250 个以上的单词。这导致快速有效的数据提取。
// select 250 more words for page#2
// “where wordIndex>212” causes the fetched words
// to begin with the 213th word in the text
Select top 250 word from RomeoAndJuliet order by wordIndex where wordIndex>212
Part 2: Format the fetched words into lines of text that fit into the specified page width
第 2 部分:将获取的单词格式化为适合指定页面宽度的文本行
Each line of text must contain enough words to fill the specified page with, but not more.
每行文本必须包含足够的单词来填充指定的页面,但不能更多。
Start line#1 with a single word and then add words 1-at-a-time until the text fits in the specified page width.
第 1 行以一个单词开头,然后一次添加 1 个单词,直到文本适合指定的页面宽度。
After the first line is fitted, we move down by a line-height and begin line#2.
在第一条线拟合后,我们向下移动一个 line-height 并开始 line#2。
Fitting the words on the line requires measuring each additional word added on a line. When the next word would exceed the line width, that extra word is moved to the next line.
在行上拟合单词需要测量在一行中添加的每个额外单词。当下一个单词超过行宽时,该额外单词将移至下一行。
A word can be measured using Html Canvases context.measureText
method.
可以使用 Html Canvasescontext.measureText
方法测量一个词。
This code will take a set of words (like the 250 words fetched from the database) and will format as many words as possible to fill the page size.
此代码将采用一组单词(如从数据库中提取的 250 个单词),并将尽可能多地格式化单词以填充页面大小。
maxWidth
is the maximum pixel width of a line of text.
maxWidth
是一行文本的最大像素宽度。
maxLines
is the maximum number of lines that will fit on a page.
maxLines
是适合一页的最大行数。
function textToLines(words,maxWidth,maxLines,x,y){
var lines=[];
while(words.length>0 && lines.length<=maxLines){
var line=getOneLineOfText(words,maxWidth);
words=words.splice(line.index+1);
lines.push(line);
wordCount+=line.index+1;
}
return(lines);
}
function getOneLineOfText(words,maxWidth){
var line="";
var space="";
for(var i=0;i<words.length;i++){
var testWidth=ctx.measureText(line+" "+words[i]).width;
if(testWidth>maxWidth){return({index:i-1,text:line});}
line+=space+words[i];
space=" ";
}
return({index:words.length-1,text:line});
}
Part 3: Display the lines of text using SVG
第 3 部分:使用 SVG 显示文本行
The SVG Text element is a true html element that can be read, selected and searched.
SVG Text 元素是一个真正的 html 元素,可以读取、选择和搜索。
Each individual line of text in the SVG Text element is displayed using an SVG Tspan element.
SVG Text 元素中的每一行文本都使用 SVG Tspan 元素显示。
This code takes the lines of text which were formatted in Part#2 and displays the lines as a page of text using SVG.
此代码采用在 Part#2 中格式化的文本行,并使用 SVG 将这些行显示为文本页面。
function drawSvg(lines,x){
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
var sText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
sText.setAttributeNS(null, 'font-family', 'verdana');
sText.setAttributeNS(null, 'font-size', "14px");
sText.setAttributeNS(null, 'fill', '#000000');
for(var i=0;i<lines.length;i++){
var sTSpan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
sTSpan.setAttributeNS(null, 'x', x);
sTSpan.setAttributeNS(null, 'dy', lineHeight+"px");
sTSpan.appendChild(document.createTextNode(lines[i].text));
sText.appendChild(sTSpan);
}
svg.appendChild(sText);
$page.append(svg);
}
Here is complete code just in case the Demo link breaks:
这是完整的代码,以防演示链接中断:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
.page{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
ctx.font="14px verdana";
var pageWidth=250;
var pageHeight=150;
var pagePaddingLeft=10;
var pagePaddingRight=10;
var approxWordsPerPage=500;
var lineHeight=18;
var maxLinesPerPage=parseInt(pageHeight/lineHeight)-1;
var x=pagePaddingLeft;
var y=lineHeight;
var maxWidth=pageWidth-pagePaddingLeft-pagePaddingRight;
var text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
// # words that have been displayed
//(used when ordering a new page of words)
var wordCount=0;
// size the div to the desired page size
$pages=$(".page");
$pages.width(pageWidth)
$pages.height(pageHeight);
// Test: Page#1
// get a reference to the page div
var $page=$("#page");
// use html canvas to word-wrap this page
var lines=textToLines(getNextWords(wordCount),maxWidth,maxLinesPerPage,x,y);
// create svg elements for each line of text on the page
drawSvg(lines,x);
// Test: Page#2 (just testing...normally there's only 1 full-screen page)
var $page=$("#page2");
var lines=textToLines(getNextWords(wordCount),maxWidth,maxLinesPerPage,x,y);
drawSvg(lines,x);
// Test: Page#3 (just testing...normally there's only 1 full-screen page)
var $page=$("#page3");
var lines=textToLines(getNextWords(wordCount),maxWidth,maxLinesPerPage,x,y);
drawSvg(lines,x);
// fetch the next page of words from the server database
// (since we've specified the starting point in the entire text
// we only have to download 1 page of text as needed
function getNextWords(nextWordIndex){
// Eg: select top 500 word from romeoAndJuliet
// where wordIndex>=nextwordIndex
// order by wordIndex
//
// But here for testing, we just hardcode the entire text
var testingText="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
var testingWords=testingText.split(" ");
var words=testingWords.splice(nextWordIndex,approxWordsPerPage);
//
return(words);
}
function textToLines(words,maxWidth,maxLines,x,y){
var lines=[];
while(words.length>0 && lines.length<=maxLines){
var line=getLineOfText(words,maxWidth);
words=words.splice(line.index+1);
lines.push(line);
wordCount+=line.index+1;
}
return(lines);
}
function getLineOfText(words,maxWidth){
var line="";
var space="";
for(var i=0;i<words.length;i++){
var testWidth=ctx.measureText(line+" "+words[i]).width;
if(testWidth>maxWidth){return({index:i-1,text:line});}
line+=space+words[i];
space=" ";
}
return({index:words.length-1,text:line});
}
function drawSvg(lines,x){
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
var sText = document.createElementNS('http://www.w3.org/2000/svg', 'text');
sText.setAttributeNS(null, 'font-family', 'verdana');
sText.setAttributeNS(null, 'font-size', "14px");
sText.setAttributeNS(null, 'fill', '#000000');
for(var i=0;i<lines.length;i++){
var sTSpan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
sTSpan.setAttributeNS(null, 'x', x);
sTSpan.setAttributeNS(null, 'dy', lineHeight+"px");
sTSpan.appendChild(document.createTextNode(lines[i].text));
sText.appendChild(sTSpan);
}
svg.appendChild(sText);
$page.append(svg);
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Text split into "pages"<br>(Selectable & Searchable)</h4>
<div id="page" class="page"></div>
<h4>Page 2</h4>
<div id="page2" class="page"></div>
<h4>Page 3</h4>
<div id="page3" class="page"></div>
</body>
</html>
回答by Friedrich
I have got a solution with quite simple, changable css markup and 3 pretty short js functions.
我有一个非常简单、可更改的 css 标记和 3 个非常短的 js 函数的解决方案。
First I have created two div-elements, from which one is hidden but contains the whole text and the other is displayed but empty yet. The HTMLwould look like this:
首先,我创建了两个 div 元素,其中一个是隐藏的,但包含整个文本,另一个是显示的,但还为空。该HTML应该是这样的:
<div id="originalText">
some text here
</div>
<div id="paginatedText"></div>
the CSSfor these two is:
这两个的CSS是:
#originalText{
display: none; // hides the container
}
#paginatedText{
width: 300px;
height: 400px;
background: #aaa;
}
also I made the css ready for a class names page which looks like this:
我还为类名页面准备了 css,如下所示:
.page{
padding: 0;
width: 298;
height: 398px; // important to define this one
border: 1px solid #888;
}
the really important part is to define the height because otherwise the pages will just get streched when we fill in the words later on.
真正重要的部分是定义高度,否则当我们稍后填写单词时页面会被拉伸。
Now comes the important part. The JavaScriptfunctions. The comments should speak for themself.
现在是重要的部分。在JavaScript的功能。评论应该不言自明。
function paginateText() {
var text = document.getElementById("originalText").innerHTML; // gets the text, which should be displayed later on
var textArray = text.split(" "); // makes the text to an array of words
createPage(); // creates the first page
for (var i = 0; i < textArray.length; i++) { // loops through all the words
var success = appendToLastPage(textArray[i]); // tries to fill the word in the last page
if (!success) { // checks if word could not be filled in last page
createPage(); // create new empty page
appendToLastPage(textArray[i]); // fill the word in the new last element
}
}
}
function createPage() {
var page = document.createElement("div"); // creates new html element
page.setAttribute("class", "page"); // appends the class "page" to the element
document.getElementById("paginatedText").appendChild(page); // appends the element to the container for all the pages
}
function appendToLastPage(word) {
var page = document.getElementsByClassName("page")[document.getElementsByClassName("page").length - 1]; // gets the last page
var pageText = page.innerHTML; // gets the text from the last page
page.innerHTML += word + " "; // saves the text of the last page
if (page.offsetHeight < page.scrollHeight) { // checks if the page overflows (more words than space)
page.innerHTML = pageText; //resets the page-text
return false; // returns false because page is full
} else {
return true; // returns true because word was successfully filled in the page
}
}
At the end I just called the paginateText
function with
最后我只是paginateText
用
paginateText();
This whole skript works for every text and for every style of the pages.
整个脚本适用于每个文本和页面的每种样式。
So you can change the font and the font size and even the size of the pages.
因此,您可以更改字体和字体大小甚至页面的大小。
I also have a jsfiddlewith everything in there.
我也有一个jsfiddle 里面的所有东西。
If I have forgotten anything or you have a question feel free to comment and make suggestions or ask questions.
如果我忘记了什么或者您有任何问题,请随时发表评论并提出建议或提出问题。
回答by RoboticRenaissance
I don't have enough rep to make a comment yet, but I just wanted to say that Eric's answer works beautifully. I'm creating an eReader, except that it reads HTML files, and you can use it for not-ready-for-publication text. There are two pages that can be seen and they resize only when you press a button.
我还没有足够的代表发表评论,但我只想说 Eric 的回答非常有效。我正在创建一个电子阅读器,但它可以读取 HTML 文件,您可以将它用于未准备好发布的文本。有两个页面可以看到,并且只有在您按下按钮时它们才会调整大小。
I made many modifications. There was only only one small flaw that I found, though. When you check to see if the last word falls off the edge of the page, and it does, you need to add that word back to the list. Simply put, in the first case of the if statement, put in the line i--; in order to go back and put that word on the next page.
我做了很多修改。不过,我只发现了一个小缺陷。当您检查最后一个单词是否从页面边缘脱落时,您需要将该单词添加回列表中。简单的说,在if语句的第一种情况下,放入i--行;为了回去把那个词放在下一页。
Here's my modifications:
这是我的修改:
- made it all into a function, with the arguments (content,target).
- added a variable backUpContent, for reuse when I resize the pages.
- changed newPage to an invisible testPage and added an array page[i], containing the contents of each page, for easily going back and forth after ordering the pages.
- added the line "pC++;", a pagecounter, to the first part of the else statement.
- changed .text to .html, so that it wouldn't count the tags as their text equivalents.
- I designed it around 1 or 2 div's with changing content, rather than many, many divs that hide and show.
- There are any more inserts I haven't gotten around to yet.
- 将其全部放入一个函数中,并带有参数 (content,target)。
- 添加了一个变量 backUpContent,以便在我调整页面大小时重复使用。
- 将 newPage 改为不可见的 testPage 并添加了一个数组 page[i],包含每个页面的内容,以便在对页面进行排序后方便地来回切换。
- 在 else 语句的第一部分添加了一行“pC++;”,一个页面计数器。
- 将 .text 更改为 .html,这样它就不会将标签视为它们的文本等效项。
- 我围绕 1 或 2 个具有变化内容的 div 设计它,而不是许多隐藏和显示的 div。
- 还有更多的插入我还没有解决。
If you wanted to keep something like whole paragraphs on the same page, change the line
如果您想在同一页面上保留整个段落之类的内容,请更改行
pageText + ' ' + words[i]
to
到
pageText + '</p><p>' + words[i]
and the line
和线
words = content.split(' ');
to
到
words = content.split('</p><p>');
But you should only use that if you're sure that each of the elements like that are small enough to go on one page.
但是,仅当您确定每个类似的元素都足够小以显示在一页上时,才应该使用它。
Eric's solution is exactly the piece I was missing. I was going to ask my own question, but I finally found this page in the suggestions after typing almost all of my question. The wording of the question is a bit confusing, though.
Eric 的解决方案正是我所缺少的部分。我本来要问我自己的问题,但在输入了我几乎所有的问题后,我终于在建议中找到了这个页面。不过,这个问题的措辞有点令人困惑。
Thank You Eric!
谢谢埃里克!
回答by alphakevin
Another idea is using CSS columnto split html content, this reflow is done by browser it self so it will be very fast, the next step is inserting each page content into dom, I have done this by duplicating whole column and scroll each page to the cropped window, see codepen example:
另一个想法是使用CSS 列来拆分 html 内容,此重排由浏览器自行完成,因此速度非常快,下一步是将每个页面内容插入 dom,我通过复制整列并将每个页面滚动到裁剪后的窗口,参见 codepen 示例:
https://codepen.io/julientaq/pen/MBryxr
https://codepen.io/julientaq/pen/MBryxr
const pageWidth = 320;
const content = document.getElementById('content');
const totalWidth = content.scrollWidth;
const totalPages = totalWidth / pageWidth;
console.log('totalPages', totalPages);
let contentVisible = true;
const button = document.getElementById('btn-content');
const buttonText = document.getElementById('btn-content-text');
const showHideContent = () => {
contentVisible = !contentVisible;
content.style.display = contentVisible ? 'block' : 'none';
buttonText.innerText = contentVisible ? 'Hide' : 'Show';
}
button.addEventListener('click', showHideContent);
const html = content.innerHTML;
const container = document.getElementById('container');
// console.log('content', content);
for (let p = 0; p < totalPages; p++) {
const page = document.createElement('div');
page.innerHTML = html;
page.className = 'page';
page.style.cssText = `
width: ${totalWidth}px;
transform: translateX(-${p * pageWidth}px);
`;
const pageClip = document.createElement('div');
pageClip.className = 'page-clip';
pageClip.appendChild(page);
const pageWrapper = document.createElement('div');
pageWrapper.className = 'page-wrapper';
pageWrapper.appendChild(pageClip);
container.appendChild(pageWrapper);
}
showHideContent();
This is very suitable for few paged content, but not OK for large content, you will get alot of wasted DOM element that will never be shown.
这非常适合少量分页内容,但不适用于大内容,你会得到很多永远不会显示的浪费的 DOM 元素。
But I think there must be better ideas like combining other answers, using javascript to help splitting column result.
但我认为必须有更好的想法,比如结合其他答案,使用 javascript 来帮助拆分列结果。
回答by Bergi
That's simple, and no javascript is needed. The paged media type
is supported since CSS2. See http://www.w3.org/TR/CSS21/page.html(or current CSS3 module) for supported properties.
这很简单,不需要 javascript。在paged media type
由于支持CSS2。有关支持的属性,请参阅http://www.w3.org/TR/CSS21/page.html(或当前 CSS3 模块)。