Site Search

jQueryとCSSでつくるiPodのカレンダーのようなカレンダー

iPod(30GBとかの普通のやつ)に入ってるような
四隅が角丸のカレンダーを文字サイズ可変で作ってみました。
もちろん縦にも横にも広がります。

カレンダーのHTMLを用意する

まずはカレンダーのHTMLを用意します。
曜日の関係もあるのでtableを使ってマークアップします。
この辺はよくある感じです。

前月・次月は当月と区別するためにclassにgrayを割り当てました。
本当はprevとかnextがいいかも。まぁoffとかでも…適当でいいです。


<table summary="カレンダー" class="icalendar">
<thead>
<tr>
<td>Sun</td>
<td>Mon</td>
<td>Tue</td>
<td>Wed</td>
<td>Thu</td>
<td>Fri</td>
<td>Sat</td>
</tr>
</thead>
<tbody>
<tr>
<td class="gray">25</td>
<td class="gray">26</td>
<td class="gray">27</td>
<td class="gray">28</td>
<td class="gray">29</td>
<td class="gray">30</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td>10</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>14</td>
<td>15</td>
</tr>
<tr>
<td>16</td>
<td>17</td>
<td>18</td>
<td>19</td>
<td>20</td>
<td>21</td>
<td>22</td>
</tr>
<tr>
<td>23</td>
<td>24</td>
<td>25</td>
<td>26</td>
<td>27</td>
<td>28</td>
<td>29</td>
</tr>
<tr>
<td>30</td>
<td>31</td>
<td class="gray">1</td>
<td class="gray">2</td>
<td class="gray">3</td>
<td class="gray">4</td>
<td class="gray">5</td>
</tr>
</tbody>
</table>

デザインにあわせてマークアップしてみる

iPodのカレンダーを見ると↑のようなデザインになってます。
左が選択中、真ん中が当月、右が前月・次月です。
(なんとなくで作ってるので色味とか違ったりしますけど)

最初に書いたように角丸かつフォントサイズ可変でつくるので
上のデザインを実現するには無駄なspan要素を大量に使う必要があります。

具体的には↓のコードで角丸サイズ可変が実現できます。


<td><span class="lt"><span class="rt">1<span class="lb"></span><span class="rb"></span></span></span></td>

全部のtdにこれを入れるのは面倒くさいので省略しますが…
見ればわかるとおり何の意味ももたない無駄なspanが大量に入ってます。
とりあえずそこは無視してスタイルをあてます。


table.icalendar {
margin-top: 1em;
border-collapse: separate;
font-size: 80%;
}

table.icalendar tbody td {
width: 3.8em;
height: 2.8em;
}

table.icalendar thead td {
font-weight: bold;
text-align: center;
}

まずはtableとtdにスタイルを指定します。
tdは上下隣り合うtdと離れているのでborder-collapseプロパティの値をseparateに指定します。

また今回はデザインに併せてある程度の幅と高さを持たせるために
tdにwidth: 3.8em, height: 2.8emを指定しています。

カレンダーの背景画像 カレンダーの背景画像 カレンダーの背景画像

↑の画像をspanの背景に指定していきます。大きめの画像のほうが拡大に耐えられます。
説明はソース見たほうが早いと思うので…


table.icalendar tbody td span.lt {
padding-left: .4em;
display: block;
height: 2.8em;
position: relative;
font-weight: bold;
overflow: hidden;
}
table.icalendar tbody td span { background: #FFF url(../img/td_bg_off.gif) no-repeat left top }

table.icalendar tbody td span span.rt {
padding-top: .2em;
display: block;
height: 3.8em;
background-position: right top;
}

table.icalendar tbody td span span.lb,
table.icalendar tbody td span span.rb {
display: block;
width: 5px;
height: 5px;
position: absolute;
bottom: 0;
}

table.icalendar tbody td span span.lb {
width: 4.2em;
left: 0;
background-position: left bottom;
}

table.icalendar tbody td span span.rb {
right: 0;
background-position: right bottom;
}

span.lbとspan.rbは親のspanに対して絶対配置でそれぞれ右下と左下に配置するんですが
下のborder部分を表示するためにspan.lbのwidthを親のtdと同じに指定します。

IEで背景がずれる

IE6では絶対配置のspanがright: 0, bottom: 0に配置されず1px隙間ができるので


* html table.icalendar tbody td span span.lb {
margin-bottom: -1px;
}

* html table.icalendar tbody td span span.rb {
margin: 0 -1px -1px 0;
}

で隙間をなくします。
もっといい方法ないのかな…

灰色部分とホバー部分は下記のように上書きします。


table.icalendar tbody td.gray span { color: #555; background-image: url(../img/td_bg_gray.gif) }
table.icalendar tbody td.hover span { color: #FFF; background-image: url(../img/td_bg_on.gif) }

jQueryを使ってtd:hoverに対応させる

例によってIE6がtd:hoverに対応していないので
jQueryを使ってtd:hover時にクラスをあてます。


$(function(){
$("table.icalendar tbody td").hover(function(){
$(this).addClass("hover");
},function(){
$(this).removeClass("hover");
});
});

これをHTMLファイルのheadか任意の外部JSファイルに記述します。

デザインのためだけのspan要素をJSで書き出す

ここまでで一通り完成なんですけど
当然ながら、無意味なspanをようさん使うのはイヤ、という考えの人が大半やと思います。
というよりもいちいち全部にspanとか入れるのがまず面倒くさいし…

僕もそうですけど、HTMLで無駄なdiv要素とかspan要素とか入れるのはイヤやけど
JSで追加するのは許せるという人は(角丸スクリプトの人気を見る限り)多いと思います。

そんなわけでさっきの


<td><span class="lt"><span class="rt">1<span class="lb"></span><span class="rb"></span></span></span></td>

をjQueryを使って実現します。
ここまでで、もしほんまに全部のtdの中身を↑に書き換えてる人がいたらほんまにすいません。全部


<td>1</td>

に戻してください…


$("table.icalendar tbody td").each(function(){
$(this).html("<span class='lt'><span class='rt'>"+$(this).html()+"<span class='lb'></span><span class='rb'></span></span></span>");
});

実に簡単で分かりやすいです…
これをさっきのhoverの部分とあわせて


$(function(){
$("table.icalendar tbody td").each(function(){
$(this).html("<span class='lt'><span class='rt'>"+$(this).html()+"<span class='lb'></span><span class='rb'></span></span></span>");
}).hover(function(){
$(this).addClass("hover");
},function(){
$(this).removeClass("hover");
});
});

として、HTMLファイルのheadか任意の外部JSファイルに記述すれば完成です。

hover画像のプリロード

ところで、このままいくとhover時の画像はtdにカーソルがのるまで読みこまれず
最初に乗せたときに案の定チラっと白くなります。
そこまで気にする人は以下のコードでプリロードすればいいです。


$(function(){
var hoverImg = new Image();
hoverImg.src= "img/td_bg_on.gif";
});

iPodのカレンダー見てこれいいなぁと思いながら作ったものの
正直なんや微妙な大きさで使いどころはないんですけど…

完成

サンプル

一応CSSファイルを置いておきます style.css
あ、画像はテキトーに右クリック保存とかでどうぞ。

動作環境
Windows: IE6, IE7, Firefox3, Opera9.5, Safari3, Chromeで確認

何か役に立つことがあったらシェアしてみてください

このエントリーをはてなブックマークに追加

Leave a comment

Comment Form
Name(required)
Email(required)
URL
Comment(required)
You can use some HTML tags for decorating texts.
(a, blockquote, ul, ol, strong, em)

Trackbacks: 0

Trackback URL for this entry
Listed below are links to weblogs that reference
jQueryとCSSでつくるiPodのカレンダーのようなカレンダー from 5509

Author

nori
nori
- UI Engineer
Location
- 35.671643, 139.710752