検索ボックス【仮】
2024年4月15日
みなさんこんにちは。
ケミストのWeb担当みやのです。
「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。
今回は「ブログ記事の検索ボックス」を作ってみようと思います。
ありがたいことに、うちの先輩が動画で私の作った記事を使ってくれているのですが「どこに何の記事があるのかわからないよ」というご意見をいただきましたのでCtrl+Fでええやんけじゃあ検索ボックスを設置しましょう!ということになりました。
Googleカスタム検索
検索といえばGoogleですね。
検索範囲を自サイトに限定すれば、サイト内検索のできあがりです。
検索する範囲をうちのサイト「www.chemist-web.com」で設定してみましょう。
するとコードが出てくるのでコピーして貼り付けます。
<script async src="https://cse.google.com/cse.js?cx=b48d3da4721944e23"></script>
<div class="gcse-search"></div>
うーん、悪くはないんですが、いまいち狙った検索結果が出ないですね。
例えば「体表面積」って入れたらちゃんと出るけど「クレアチニンクリアランス」って入れても出ない
SEO対策をちゃんとしてたらいい感じの結果になるのかなあ。
色とか結果の表示のしかたとかをさらに細かくカスタマイズできるのですが、自分でCSSを当てることはできないようです。
サイト内検索
サイト内検索を実装する方法は他にもいくつかあるようです。
参考:ウェブカツ|HTMLで検索機能を付けるには?入力フォームで見やすいサイトに!
参考:text.sakura.ne.jp|【JavaScript】サイト内検索フォーム表示ツール
参考:プログラミングスクールおすすめ10社比較!最短で上達するなら?|JavaScriptで簡単な検索ツールを作った
MixItUpのフィルター機能みたいに、検索ボックスに文字を入力すると該当する記事を絞り込んでくれるようなのを作りたいんだよォォォォ
参考:株式会社グローバルゲート|外部ページの取得と簡単な検索システムをJavascriptで作る
これが一番イメージに近いのですが、Vue.jsが難しすぎて全然わかりません/(^o^)\
tableではなくcardの一覧を対応させるにはどうすれば・・・
ページ内検索を手作りしてみよう
参考:Tips Note by TAM|検索ボックスの値をリアルタイムに取得して、部分一致の絞込み検索を実装する
なんかよさそうなのが見つかりました。
上記サイトの「さらにアレンジ」を参考に、ブログ記事一覧ページに組み込んでみます。
まずは検索ボックスを設置します。
<form>
<input type="text" name="input" class="searchBlog" placeholder="キーワードを入力してください">
</form>
スクリプトを記述します。
$(function () {
searchWord = function(){
var searchText = $(this).val(), targetText;
$('#Container a').each(function() {
targetText = $(this).text();
if (targetText.toLowerCase().indexOf(searchText.toLowerCase()) != -1) {
$(this).removeClass('hidden');
} else {
$(this).addClass('hidden');
}
});
};
$('.searchBlog').on('input', searchWord);
});
indexOfメソッドというのを使って、入力した文字と部分的に一致した場合はhiddenというクラスを外す、という処理をするみたいです。
大文字小文字どっちでも引っかかるように、toLowerCaseで小文字に統一しました。
検索ボックスに入力した段階で結果が反映されるようにしてあるのですが(そういうのをインクリメンタルサーチというらしいです)エンターを押すとフォームが送信されてページがリロードされてしまうので、エンターキーを無効化しておきます。
$(function(){
$("input").on("keydown", function(e) {
if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
return false;
} else {
return true;
}
});
});
CSSを設定します。
#Container .hidden {
display: none;
opacity: 0;
animation: fadeOut 0.5s ease-out 0s forwards;
}
@keyframes fadeOut {
0% {
display: inline;
opacity: 1;
}
99.9% {
display: inline;
opacity: 0;
}
100% {
display: none;
opacity: 0;
}
}
display:noneにはtransitionが効かないらしいので、@keyframesとopacityを併用してみました。「ふわっと消える」はできましたが「ふわっと現れる」ができないです。
検索ボックスに文字を入力した後にフィルターボタンを操作すると挙動がおかしくなりますね。クラスの付け外しがうまくいってないのかなあ。
CSSをちょっと書き換えたら「ふわっと現れる」もできたのですが、スマホでページを読み込んだ時の挙動がおかしくなり、フィルターボタンがさらにバグってしまいました。
フィルターボタンを消すしかないかな~
@media (min-width:768px) {
#Container a {
display: inline-flex;
opacity: 1;
animation: fadeIn 0.5s ease-out 0s forwards;
}
}
#Container a.hidden {
display: none;
opacity: 0;
animation: fadeOut 0.5s ease-out 0s forwards;
}
@keyframes fadeOut {
0% {
display: inline;
opacity: 1;
}
99.9% {
display: inline;
opacity: 0;
}
100% {
display: none;
opacity: 0;
}
}
@keyframes fadeIn {
0% {
display: none;
opacity: 0;
}
0.1% {
display: inline;
opacity: 0;
}
100% {
display: inline;
opacity: 1;
}
}
検索ボックスをオサレにしてみよう
参考:KodoCode|検索窓をおしゃれにするCSSスニペット9選。デザイン性に優れた検索ボックスまとめ
参考:Workship MAGAZINE|検索フィールドデザインのコードスニペット8選【CSS/JavaScript】
カッコイイのがいっぱいありますね!
とりあえず虫眼鏡アイコンを入れてみましょう。
<form>
<span class="fas fa-search form-control-feedback"></span>
<input type="text" name="input" class="searchBlog searchPc" placeholder="キーワードを入力してください">
</form>
input.searchPc {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
box-shadow: none;
background: transparent;
border: 2px solid rgba(0, 0, 0, 0.1);
height: 48px;
font-size: 16px;
font-weight: 400;
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
-ms-border-radius: 7px;
border-radius: 7px;
padding: 1em;
padding-left: 36px;
width: 500px;
max-width: 100%;
}
input:focus.searchPc {
outline: none;
box-shadow: none;
border-color: #32bdeb;
}
.form-control-feedback {
position: absolute;
z-index: 2;
display: block;
width: 40px;
height: 40px;
line-height: 48px;
text-align: center;
pointer-events: none;
color: #aaa;
}
::placeholder {
color: #aaa;
}
検索ボックスっぽくなりました!
スマホ時は虫眼鏡アイコンをタッチすると入力フォームに変形するやつを入れてみます。
<form id="content">
<input type="text" name="input" class="input searchBlog" id="search-input">
<button type="reset" class="search" id="search-btn"></button>
</form>
#content {
position: fixed;
height: 30px;
width: 280px;
margin-left: 190px;
top: 57px;
left: 80%;
transform: translate(-50%, -50%);
}
#content.on {
-webkit-animation-name: in-out;
animation-name: in-out;
-webkit-animation-duration: 0.7s;
animation-duration: 0.7s;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
}
.input {
box-sizing: border-box;
width: 30px;
height: 30px;
border: 2px solid #000;
border-radius: 50%;
background: none;
color: #000;
font-size: 16px;
font-weight: 400;
font-family: inherit;
outline: 0;
-webkit-transition: width 0.4s ease-in-out, border-radius 0.8s ease-in-out, padding 0.2s;
transition: width 0.4s ease-in-out, border-radius 0.8s ease-in-out, padding 0.2s;
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
-webkit-transform: translate(-100%, -50%);
-ms-transform: translate(-100%, -50%);
transform: translate(-100%, -50%);
}
.search {
background: none;
position: absolute;
top: 0px;
left: 0;
height: 30px;
width: 30px;
padding: 0;
border-radius: 100%;
outline: 0;
border: 0;
color: #000;
cursor: pointer;
-webkit-transition: 0.2s ease-in-out;
transition: 0.2s ease-in-out;
-webkit-transform: translate(-100%, -50%);
-ms-transform: translate(-100%, -50%);
transform: translate(-100%, -50%);
}
.search:before {
content: "";
position: absolute;
width: 16.2px;
height: 2.4px;
background-color: #000;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
margin-top: 13px;
margin-left: 8.5px;
-webkit-transition: 0.2s ease-in-out;
transition: 0.2s ease-in-out;
}
.close {
-webkit-transition: 0.4s ease-in-out;
transition: 0.4s ease-in-out;
-webkit-transition-delay: 0.4s;
transition-delay: 0.4s;
}
.close:before {
content: "";
position: absolute;
width: 16.2px;
height: 2.4px;
margin-top: -0.6px;
margin-left: -7.8px;
background-color: #000;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
-webkit-transition: 0.2s ease-in-out;
transition: 0.2s ease-in-out;
}
.close:after {
content: "";
position: absolute;
width: 16.2px;
height: 2.4px;
background-color: #000;
margin-top: -0.6px;
margin-left: -7.8px;
cursor: pointer;
-webkit-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.square {
box-sizing: border-box;
padding: 0 40px 0 10px;
width: 280px;
height: 30px;
border: 2px solid #000;
border-radius: 0;
background: rgba(255, 255, 255, 0.8);
color: #000;
font-size: 16px;
font-weight: 400;
outline: 0;
-webkit-transition: width 0.4s ease-in-out, border-radius 0.4s ease-in-out, padding 0.2s;
transition: width 0.4s ease-in-out, border-radius 0.4s ease-in-out, padding 0.2s;
-webkit-transition-delay: 0.4s, 0s, 0.4s;
transition-delay: 0.4s, 0s, 0.4s;
-webkit-transform: translate(-100%, -50%);
-ms-transform: translate(-100%, -50%);
transform: translate(-100%, -50%);
}
function expand() {
$(".search").toggleClass("close");
$(".input").toggleClass("square");
if ($('.search').hasClass('close')) {
$('.input').focus();
} else {
$('.input').blur();
}
}
$('.search').on('click', expand);
変形はロマンですね!
position:fixedで右上に固定させたのですが、iPhoneのSafariだとフォーカス時にfixedを無視して下方向に移動してしまう謎のバグがありました。
課題
というわけで、とりあえず目的のものはできたのですが、
・MixItUpのフィルターと相性が悪い
検索ボックスに文字を入力した後にフィルターボタンを操作すると挙動がおかしくなるので泣く泣くフィルターボタンをオミット
・変形する検索ボックスの不具合
変形する検索ボックスを✕で閉じると、入力した内容はリセットされるのに検索結果がリセットされない
・アニメーションしない
スマホだとフェードイン・フェードアウトしてくれない
・lazyloadが止まる?
絞り込み後、サムネ画像がいつまでも表示されない場合がある
・Safariでバグる
iPhoneのSafariでposition:fixedにした虫眼鏡アイコンにフォーカスするとたまにバグる(fixedを無視して下方向に移動しちゃう)
いつかちゃんと完成させたいです!