Qiita API
から取得した投稿内容を自分のサイトに表示するときコードブロックに行番号を表示させたかったので、JavaScriptを使わず実装する方法を考えた。
APIで取得した内容の一部
<div class="code-frame" data-lang="JavaScript">
<div class="code-lang"><span class="bold">app.js</span></div>
<div class="highlight"><pre><span></span> <span class="k">for</span><span class="p">(</span><span class="kd">let</span> <span class="nx">url</span> <span class="k">of</span> <span class="nx">urls</span><span class="p">){</span>
<span class="nx">await</span> <span class="nx">chromy</span><span class="p">.</span><span class="kr">goto</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span>
<span class="line-numbers-rows"><span></span><span></span></span></pre></div>
</div>
目標
-
pre
要素の左側に行番号を表示 - コードをコピーする時に邪魔にならない
- できれば
JavaScript
は使いたくない
イメージは下記URLの通り。
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters
#実装方法
HTML
HTML
<pre>
# 1行目
# 2行目
# 3行目
<div class="line-numbers"><span></span><span></span><span></span></div>
</pre>
pre
要素の中なので改行や空白がそのまま表示されるので注意。
<div class="line-numbers">
内に行数分だけ<span></span>
を設置する。あまりスマートでは無いのでJavaScriptかテンプレートエンジンで行数分ループするのがよさそう
Pythonだとこんな感じ
print('<div class="line-numbers">'+'<span></span>'*3+'<div>')
CSS
CSS
pre {
position: relative;
padding: 20px 50px;
}
.line-numbers {
position: absolute;
top: 0;
left: 0;
padding: 20px 5px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-right: 1px solid #999;
width: 50px;
}
.line-numbers > span {
float: left;
display: block;
counter-increment: linenumber;
text-align: right;
width: 100%;
}
.line-numbers > span::after {
content: counter(linenumber);
}
JavaScriptを使わずに行番号を加算していくのにCSS counters
を使って実装した。
counter-increment: linenumber;
でlinenumber変数を加算して疑似要素の::after
の中にcontent: counter(linenumber);
で表示させる。
表示結果
コード全体
index.html
<html>
<body>
<pre>
<span># 1行目</span>
<span># 2行目</span>
<span># 3行目</span>
<div class="line-numbers"><span></span><span></span><span></span></div>
</pre>
<style>
body{
margin:50px;
background:#ddd;
}
pre {
position: relative;
padding: 20px 50px;
}
.line-numbers {
position: absolute;
top: 0;
left: 0;
padding: 20px 5px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-right: 1px solid #999;
width: 50px;
}
.line-numbers > span {
float: left;
display: block;
counter-increment: linenumber;
text-align: right;
width: 100%;
}
.line-numbers > span::after {
content: counter(linenumber);
}
</style>
</body>
</html>