セレクトボックスをオシャレにする
2022年12月5日
みなさんこんにちは。
ケミストのWeb担当みやのです。
「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。
今回は前回の続きです。セレクトボックスをもっとオシャレにしてみましょう。今回も選択肢は歴代ジョジョです!
参考:KodoCode|選択プルダウン(SELECT~OPTION)をおしゃれにするCSSスニペット15選。
参考:こぴぺっと|コピペでできる!cssとhtmlのみでフォームのセレクトボックスをいい感じにするデザイン8選
① 吹き出し
吹き出し型のリストがふわっと現れます。
選択肢を選ぶとふわっと消えます。
右の矢印がくるっと回転します。
初期状態のテキストはplaceholder属性で設定します。
<select name="select1" id="select1" class="custom-select" placeholder="選択してください">
<option value="jojo1">ジョナサン・ジョースター</option>
<option value="jojo2">ジョセフ・ジョースター</option>
<option value="jojo3">空条承太郎</option>
<option value="jojo4">東方仗助</option>
<option value="giogio5">ジョルノ・ジョバァーナ</option>
<option value="jojo6">空条徐倫</option>
<option value="jojo7">ジョニィ・ジョースター</option>
<option value="jojo8">東方定助</option>
<option value="jojo9">ジョディオ・ジョースター</option>
</select>
.custom-select-wrapper {
position: relative;
display: inline-block;
user-select: none;
}
.custom-select-wrapper select {
display: none;
}
.custom-select {
position: relative;
display: inline-block;
}
.custom-select-trigger {
position: relative;
display: block;
width: 300px;
padding: 0 60px 0 16px;
font-size: 16px;
font-weight: 400;
color: #fff;
line-height: 60px;
background: #5c9cd8;
border-radius: 4px;
cursor: pointer;
}
.custom-select-trigger:after {
position: absolute;
display: block;
content: '';
width: 10px;
height: 10px;
top: 50%;
right: 25px;
margin-top: -3px;
border-bottom: 1px solid #fff;
border-right: 1px solid #fff;
transform: rotate(45deg) translateY(-50%);
transition: all .4s ease-in-out;
transform-origin: 50% 0;
}
.custom-select.opened .custom-select-trigger:after {
margin-top: 3px;
transform: rotate(-135deg) translateY(-50%);
}
.custom-options {
position: absolute;
display: block;
top: 100%;
left: 0;
right: 0;
min-width: 100%;
margin: 15px 0;
border: 1px solid #b5b5b5;
border-radius: 4px;
box-sizing: border-box;
box-shadow: 0 2px 1px rgba(0, 0, 0, .07);
background: #fff;
transition: all .4s ease-in-out;
opacity: 0;
visibility: hidden;
pointer-events: none;
transform: translateY(-15px);
}
.custom-select.opened .custom-options {
opacity: 1;
visibility: visible;
pointer-events: all;
transform: translateY(0);
}
.custom-options:before {
position: absolute;
display: block;
content: '';
bottom: 100%;
right: 25px;
width: 7px;
height: 7px;
margin-bottom: -4px;
border-top: 1px solid #b5b5b5;
border-left: 1px solid #b5b5b5;
background: #fff;
transform: rotate(45deg);
transition: all .4s ease-in-out;
}
.option-hover:before {
background: #f9f9f9;
}
.custom-option {
position: relative;
display: block;
padding: 0 22px;
border-bottom: 1px solid #b5b5b5;
font-size: 16px;
font-weight: 700;
color: #b5b5b5;
line-height: 47px;
cursor: pointer;
transition: all .4s ease-in-out;
}
.custom-option:first-of-type {
border-radius: 4px 4px 0 0;
}
.custom-option:last-of-type {
border-bottom: 0;
border-radius: 0 0 4px 4px;
}
.custom-option:hover, .custom-option.selection {
background: #f9f9f9;
}
$(".custom-select").each(function() {
var classes = $(this).attr("class"),
id = $(this).attr("id"),
name = $(this).attr("name");
var template = '<div class="' + classes + '">';
template += '<span class="custom-select-trigger">' + $(this).attr("placeholder") + '</span>';
template += '<div class="custom-options">';
$(this).find("option").each(function() {
template += '<span class="custom-option ' + $(this).attr("class") + '" data-value="' + $(this).attr("value") + '">' + $(this).html() + '</span>';
});
template += '</div></div>';
$(this).wrap('<div class="custom-select-wrapper"></div>');
$(this).hide();
$(this).after(template);
});
$(".custom-option:first-of-type").hover(function() {
$(this).parents(".custom-options").addClass("option-hover");
}, function() {
$(this).parents(".custom-options").removeClass("option-hover");
});
$(".custom-select-trigger").on("click", function() {
$('html').one('click',function() {
$(".custom-select").removeClass("opened");
});
$(this).parents(".custom-select").toggleClass("opened");
event.stopPropagation();
});
$(".custom-option").on("click", function() {
$(this).parents(".custom-select-wrapper").find("select").val($(this).data("value"));
$(this).parents(".custom-options").find(".custom-option").removeClass("selection");
$(this).addClass("selection");
$(this).parents(".custom-select").removeClass("opened");
$(this).parents(".custom-select").find(".custom-select-trigger").text($(this).text());
});
② 下からふわっと
リストが下からふわっと現れます。
選択済の選択肢の右にチェックマークが付きます。
右の矢印の向きが切り替わります。
<div class="sel">
<select name="select2" id="select2">
<option value="" disabled>選択してください</option>
<option value="jojo1">ジョナサン・ジョースター</option>
<option value="jojo2">ジョセフ・ジョースター</option>
<option value="jojo3">空条承太郎</option>
<option value="jojo4">東方仗助</option>
<option value="giogio5">ジョルノ・ジョバァーナ</option>
<option value="jojo6">空条徐倫</option>
<option value="jojo7">ジョニィ・ジョースター</option>
<option value="jojo8">東方定助</option>
<option value="jojo9">ジョディオ・ジョースター</option>
</select>
</div>
.sel {
font-size: 1rem;
display: inline-block;
margin: 1em 0.5em;
width: 250px;
background-color: transparent;
position: relative;
cursor: pointer;
border-bottom: 4px solid rgba(0, 0, 0, 0.3);
}
.sel::before {
position: absolute;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f063";
font-size: 1em;
color: #838e95;
right: 20px;
top: calc(50% - 0.7em);
}
.sel.active::before {
transform: rotateX(-180deg);
}
.sel__placeholder {
display: block;
font-size: 1em;
color: #838e95;
padding: 0.2em 0.5em;
text-align: left;
pointer-events: none;
user-select: none;
visibility: visible;
}
.sel.active .sel__placeholder {
visibility: hidden;
}
.sel__placeholder::before {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
padding: 0.2em 0.5em;
content: attr(data-placeholder);
visibility: hidden;
}
.sel.active .sel__placeholder::before {
visibility: visible;
}
.sel__box {
position: absolute;
top: calc(100% + 4px);
left: -4px;
display: none;
list-style-type: none;
text-align: left;
font-size: 1em;
background-color: #FFF;
width: calc(100% + 8px);
box-sizing: border-box;
}
.sel.active .sel__box {
display: block;
animation: fadeInUp 500ms;
}
.sel__box__options {
display: list-item;
font-size: 1em;
color: #838e95;
padding: 0.5em 1em;
user-select: none;
}
.sel__box__options::after {
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: "\f00c";
font-size: 0.5em;
margin-left: 5px;
display: none;
color: #dc3545;
}
.sel__box__options.selected::after {
display: inline;
}
.sel__box__options:hover {
background-color: #ebedef;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translate3d(0, 20px, 0);
}
to {
opacity: 1;
transform: none;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
$('.sel').each(function() {
$(this).children('select').css('display', 'none');
var $current = $(this);
$(this).find('option').each(function(i) {
if (i == 0) {
$current.prepend($('<div>', {
class: $current.attr('class').replace(/sel/g, 'sel__box')
}));
var placeholder = $(this).text();
$current.prepend($('<span>', {
class: $current.attr('class').replace(/sel/g, 'sel__placeholder'),
text: placeholder,
'data-placeholder': placeholder
}));
return;
}
$current.children('div').append($('<span>', {
class: $current.attr('class').replace(/sel/g, 'sel__box__options'),
text: $(this).text()
}));
});
});
$('.sel').click(function() {
$(this).toggleClass('active');
});
$('.sel__box__options').click(function() {
var txt = $(this).text();
var index = $(this).index();
$(this).siblings('.sel__box__options').removeClass('selected');
$(this).addClass('selected');
var $currentSel = $(this).closest('.sel');
$currentSel.children('.sel__placeholder').text(txt);
$currentSel.children('select').prop('selectedIndex', index + 1);
});
③ カード型
カード型のリストが重なったようなデザインです。
optionの文字がどうやっても縦中央にできません。margin-leftは効いたのになぁ...今後の課題とします。
<select class="old-select">
<option value="">選択してください</option>
<option value="jojo1">ジョナサン・ジョースター</option>
<option value="jojo2">ジョセフ・ジョースター</option>
<option value="jojo3">空条承太郎</option>
<option value="jojo4">東方仗助</option>
<option value="giogio5">ジョルノ・ジョバァーナ</option>
<option value="jojo6">空条徐倫</option>
<option value="jojo7">ジョニィ・ジョースター</option>
<option value="jojo8">東方定助</option>
<option value="jojo9">ジョディオ・ジョースター</option>
</select>
<div class="new-select">
<div class="selection">
<p> <span></span> <i></i> </p>
<span></span>
</div>
</div>
.old-select {
position: absolute;
top: -9999px;
left: -9999px;
padding: auto;
}
.new-select {
width: 300px;
height: 50px;
text-align: left;
vertical-align: middle;
color: #444;
line-height: 25px;
position: relative;
}
.new-select .selection:active {
transform: rotateX(42deg);
-o-transform: rotateX(42deg);
-ms-transform: rotateX(42deg);
-moz-transform: rotateX(42deg);
-webkit-transform: rotateX(42deg);
transform-style: preserve-3d;
-o-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transform-origin: top;
-o-transform-origin: top;
-ms-transform-origin: top;
-moz-transform-origin: top;
-webkit-transform-origin: top;
transition: transform 200ms ease-in-out;
-o-transition: -o-transform 200ms ease-in-out;
-ms-transition: -ms-transform 200ms ease-in-out;
-moz-transition: -moz-transform 200ms ease-in-out;
-webkit-transition: -webkit-transform 200ms ease-in-out;
}
.new-select .selection {
width: 100%;
height: 100%;
padding-left: 1rem;
background-color: #fff;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
border: solid 2px #333;
cursor: pointer;
position: relative;
z-index: 20;
transform: rotateX(0deg);
-o-transform: rotateX(0deg);
-ms-transform: rotateX(0deg);
-moz-transform: rotateX(0deg);
-webkit-transform: rotateX(0deg);
transform-style: preserve-3d;
-o-transform-style: preserve-3d;
-ms-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
transform-origin: top;
-o-transform-origin: top;
-ms-transform-origin: top;
-moz-transform-origin: top;
-webkit-transform-origin: top;
transition: transform 200ms ease-in-out;
-o-transition: -o-transform 200ms ease-in-out;
-ms-transition: -ms-transform 200ms ease-in-out;
-moz-transition: -moz-transform 200ms ease-in-out;
-webkit-transition: -webkit-transform 200ms ease-in-out;
}
.new-select .selection p {
width: calc(100% - 60px);
position: relative;
transition: all 200ms ease-in-out;
-o-transition: all 200ms ease-in-out;
-ms-transition: all 200ms ease-in-out;
-moz-transition: all 200ms ease-in-out;
-webkit-transition: all 200ms ease-in-out;
}
.new-select .selection:hover p, .new-select .selection.open p {
color: #32bdeb;
}
.new-select .selection i {
display: block;
width: 2px;
height: 40px;
position: absolute;
right: -1px;
top: 15%;
bottom: 15%;
border: none;
background-color: #333;
}
.new-select .selection > span {
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 14px 8px 0 8px;
border-color: #333 transparent transparent transparent;
position: absolute;
top: 18px;
right: 22px;
}
.new-select .selection.open > span {
width: 0;
height: 0;
border-style: solid;
border-width: 0 8px 14px 8px;
border-color: transparent transparent #333 transparent;
}
.new-option {
text-align: left;
padding-left: 1rem;
background-color: #fff;
cursor: pointer;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
position: relative;
margin-top: 1px;
position: absolute;
left: 0;
right: 0;
border: solid 2px #333;
transition: all 300ms ease-in-out;
-o-transition: all 300ms ease-in-out;
-ms-transition: all 300ms ease-in-out;
-moz-transition: all 300ms ease-in-out;
-webkit-transition: all 300ms ease-in-out;
}
.new-option p {
width: calc(100% - 60px);
}
.new-option.reveal:hover {
background-color: #444;
color: #f5f5f5;
}
$(document).ready(function(){
var countOption = $('.old-select option').size();
function openSelect(){
var heightSelect = $('.new-select').height();
var j=1;
$('.new-select .new-option').each(function(){
$(this).addClass('reveal');
$(this).css({
'box-shadow':'0 1px 1px rgba(0,0,0,0.1)',
'left':'0',
'right':'0',
'top': j*(heightSelect+1)+'px'
});
j++;
});
}
function closeSelect(){
var i=0;
$('.new-select .new-option').each(function(){
$(this).removeClass('reveal');
if(i<countOption-3){
$(this).css('top',0);
$(this).css('box-shadow','none');
}
else if(i===countOption-3){
$(this).css('top','3px');
}
else if(i===countOption-2){
$(this).css({
'top':'7px',
'left':'2px',
'right':'2px'
});
}
else if(i===countOption-1){
$(this).css({
'top':'11px',
'left':'4px',
'right':'4px'
});
}
i++;
});
}
if($('.old-select option[selected]').size() === 1){
$('.selection p span').html($('.old-select option[selected]').html());
}
else{
$('.selection p span').html($('.old-select option:first-child').html());
}
$('.old-select option').each(function(){
newValue = $(this).val();
newHTML = $(this).html();
$('.new-select').append(''+newHTML+'
');
});
var reverseIndex = countOption;
$('.new-select .new-option').each(function(){
$(this).css('z-index',reverseIndex);
reverseIndex = reverseIndex-1;
});
closeSelect();
$('.selection').click(function(){
$(this).toggleClass('open');
if($(this).hasClass('open')===true){openSelect();}
else{closeSelect();}
});
$('.new-option').click(function(){
var newValue = $(this).data('value');
$('.selection p span').html($(this).find('p').html());
$('.selection').click();
$('.old-select option[selected]').removeAttr('selected');
$('.old-select option[value="'+newValue+'"]').attr('selected','');
});
});
④ アンダーライン
クリックするとアンダーラインが中央から伸びます。
「選択してください」が左上に移動します。
optionの見た目はブラウザ依存です。
<div class="select4">
<select id="select4" class="sl4" required>
<option value="" selected hidden disabled></option>
<option value="jojo1">ジョナサン・ジョースター</option>
<option value="jojo2">ジョセフ・ジョースター</option>
<option value="jojo3">空条承太郎</option>
<option value="jojo4">東方仗助</option>
<option value="giogio5">ジョルノ・ジョバァーナ</option>
<option value="jojo6">空条徐倫</option>
<option value="jojo7">ジョニィ・ジョースター</option>
<option value="jojo8">東方定助</option>
<option value="jojo9">ジョディオ・ジョースター</option>
</select>
<span class="sl4_highlight"></span> <span class="sl4_selectbar"></span>
<label class="sl4_selectlabel">選択してください</label>
</div>
.select4 {
position: relative;
width: 90%;
margin: 2em auto;
text-align: center;
}
.sl4 {
position: relative;
font-family: inherit;
background-color: transparent;
width: 100%;
padding: 10px 10px 10px 0;
font-size: 18px;
border-radius: 0;
border: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
}
.sl4:focus {
outline: none;
border-bottom: 1px solid rgba(0, 0, 0, 0);
}
.select4 .sl4 {
appearance: none;
-webkit-appearance: none
}
.select4 select::-ms-expand {
display: none;
}
.select4:after {
position: absolute;
top: 18px;
right: 10px;
width: 0;
height: 0;
padding: 0;
content: '';
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid #6c757d;
pointer-events: none;
}
.sl4_selectlabel {
color: inherit;
font-size: 18px;
font-weight: normal;
position: absolute;
pointer-events: none;
left: 0;
top: 10px;
transition: 0.2s ease all;
}
.sl4:focus ~ .sl4_selectlabel, .sl4:valid ~ .sl4_selectlabel {
color: #32bdeb;
top: -20px;
transition: 0.2s ease all;
font-size: 14px;
}
.sl4_selectbar {
position: relative;
display: block;
width: 100%;
}
.sl4_selectbar:before, .sl4_selectbar:after {
content: '';
height: 2px;
width: 0;
bottom: 1px;
position: absolute;
background: #32bdeb;
transition: 0.2s ease all;
}
.sl4_selectbar:before {
left: 50%;
}
.sl4_selectbar:after {
right: 50%;
}
.sl4:focus ~ .sl4_selectbar:before, .sl4:focus ~ .sl4_selectbar:after {
width: 50%;
}
.sl4_highlight {
position: absolute;
top: 25%;
left: 0;
pointer-events: none;
opacity: 0.5;
}
⑤ ラジオボタンを応用
- 選択してください
<input type="radio">を応用したものです。
<div class="select5">
<ul class="sl5">
<li>
<input class="sl5_close" type="radio" name="awesomeness" id="close" value=""/>
<span class="sl5_label sl5_placeholder">選択してください</span>
</li>
<li class="sl5_items">
<input class="sl5_expand" type="radio" name="select5" id="opener"/>
<label class="sl5_closeLabel" for="close"></label>
<ul class="sl5_options">
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo1"/>
<label class="sl5_label" for="jojo1">ジョナサン・ジョースター</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo2"/>
<label class="sl5_label" for="jojo2">ジョセフ・ジョースター</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo3"/>
<label class="sl5_label" for="jojo3">空条承太郎</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo4"/>
<label class="sl5_label" for="jojo4">東方仗助</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="giogio5"/>
<label class="sl5_label" for="giogio5">ジョルノ・ジョバァーナ</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo6"/>
<label class="sl5_label" for="jojo6">空条徐倫</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo7"/>
<label class="sl5_label" for="jojo7">ジョニィ・ジョースター</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo8"/>
<label class="sl5_label" for="jojo8">東方定助</label>
</li>
<li>
<input class="sl5_input" type="radio" name="select5" id="jojo9"/>
<label class="sl5_label" for="jojo9">ジョディオ・ジョースター</label>
</li>
</ul>
<label class="sl5_expandLabel" for="opener"></label>
</li>
</ul>
</div>
.select5 {
display: block;
width: 90%;
height: 100%;
margin: 2em auto;
}
.select5 ul {
list-style: none;
padding: 0;
}
.select5 input {
color: inherit;
font: inherit;
margin: 0;
background: transparent;
outline: none;
border: none;
border-radius: 0;
-webkit-appearance: none;
appearance: none;
display: none;
}
.sl5 {
width: 100%;
height: 100%;
cursor: pointer;
background-color: white;
-webkit-box-shadow: 0 2px 0 white;
box-shadow: 0 2px 0 white;
border-radius: 2px;
}
.sl5_expand {
width: 0;
height: 40px;
position: absolute;
top: 0;
right: 0;
}
.sl5_expand::after {
position: absolute;
top: 1.2em;
right: 0.5em;
width: 0;
height: 0;
padding: 0;
content: '';
pointer-events: none;
border-top: 6px solid rgba(0, 0, 0, 0.3);
border-right: 6px solid transparent;
border-left: 6px solid transparent;
-webkit-transform: translate(-50%, -50%) rotate(0deg) scaleY(1.75);
transform: translate(-50%, -50%) rotate(0deg) scaleY(1.75);
-webkit-transition: all 250ms cubic-bezier(0.4, 0.25, 0.3, 1);
transition: all 250ms cubic-bezier(0.4, 0.25, 0.3, 1);
z-index: 2;
opacity: 0.6;
}
.sl5_expand:hover::after {
opacity: 1;
}
.sl5_expand:checked::after {
-webkit-transform: translate(-50%, -50%) rotate(180deg) scaleX(-1) scaleY(1.75);
transform: translate(-50%, -50%) rotate(180deg) scaleX(-1) scaleY(1.75);
}
.sl5_expandLabel {
display: block;
width: 100%;
height: 40px;
position: absolute;
top: 0;
left: 0;
cursor: pointer;
}
.sl5_close {
display: none;
}
.sl5_closeLabel {
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
display: none;
}
.sl5_items {
width: 100%;
position: absolute;
top: 0;
left: 0;
border: 2px solid #17a2b8;
border-radius: 2px;
padding-top: 40px;
}
.sl5_input {
display: none;
}
.sl5_options li {
background: #fff;
}
.sl5_label {
-webkit-transition: all 250ms cubic-bezier(0.4, 0.25, 0.3, 1);
transition: all 250ms cubic-bezier(0.4, 0.25, 0.3, 1);
display: block;
height: 0;
line-height: 40px;
overflow: hidden;
color: #3e3e3e;
background-color: #fff;
cursor: pointer;
padding-left: 20px;
}
.sl5_placeholder {
height: 40px;
vertical-align: middle;
position: absolute;
top: 0;
left: 0;
opacity: 0.6;
background-color: transparent;
}
.sl5_expand:checked + .sl5_closeLabel {
display: block;
}
.sl5_expand:checked + .sl5_closeLabel + .sl5_options .sl5_label {
height: 40px;
}
.sl5_expand:checked + .sl5_closeLabel + .sl5_options .sl5_label:hover {
background-color: #f7f7f7;
}
.sl5_expand:checked + .sl5_closeLabel + .sl5_options + .sl5_expandLabel {
display: none;
}
.sl5_input:checked + .sl5_label {
height: 40px;
margin-top: -40px;
}
まとめ
どれにするか、迷ってしまいますね。
まあうちの問い合わせフォームにセレクトボックスはないんですけどね。
次回は、セレクトボックスの選択結果に応じて表示される内容が変わるページを作ってみたいと思います。