I LOVE YOU, 唇噛んだ

ジャンル問わず色々つらつらと

カテゴリ「code」に属する投稿2件]

どうも、去年くらいに家焼肉がしたくて焼肉用グリルを買っていたんですが、しみじみ買ってて良かったと思ったジョーです。こんにちは!
猛烈に「焼肉食べたいな」と思った時、スーパーで値引きされて1,200円くらいになっていた焼肉用牛カルビ&豚カルビのセットを買い、家でのんびりビール開けながら食べ、トータル1,500円くらいで焼肉晩酌が出来るから最高だな…と感じていました。笑



現在は "details "と "summary "タグを使用すればとっても簡単にアコーディオンが設置出来ますよね。
しかも "details "要素のname属性を付ければ、常に1つのアコーディオンしか開かない(開いていた奴は自動的に閉じる)排他的なアコーディオンの実装まで出来ちゃいます。簡単で素晴らしい~!
と言う訳でうちのサイトも最近色々弄った際に色々アコーディオンにしました。

アコーディオンの開閉アニメーションや挙動について更にJavaScriptを使っていたんですが、初めは "summary" 要素をクリックすると、対応する "accordion" 要素が滑らかに開閉するアニメーションだけを使っていました。

で、確認をしていると、新しい要素を開いて元々の開いていた要素を閉じる際、閉じる要素がはちゃめちゃに長文だとさっきまでスクロールで下りた分はそのままになってしまうので「え?私は何を見ていたんだっけ?」とページ内で迷子になってしまいました。
しょうがないかな~とも思ったんですが、やっぱストレス!!!新しくアコーディオンの要素を開いたらそっちの先頭に戻りたい!と思ったのでJavaScriptを更に追加することに。

調べても全然でてこなかったので、ChatGPTに何度も相談しトライ&エラーを重ねてやっと理想的な動きに辿り着いたので、折角なので残しておきます。コーダーさんでも何でもない奴なのでプロが見たらおかしいことがあるかもしれませんが、動いてるからええ!の勢いです(笑)
7/25からずっとやってました…😂絵を描いてても頭の片隅でずっと考えて気になっていたからやっと落ち着いて他の事に集中できる~。


▼やりたいこと
  • 新しいアコーディオンを開いて元々開いていた要素が閉じる時、元々開いていた要素の分上方向にスクロールする。
  • 既に開いていた要素が閉じる際にスクロール位置を調整する時、新しく開いたアコーディオンの先頭の、更に0.5remだけ上の位置に戻る。(余白なくビッタビタに上がるのがちょっと気持ち悪かったので…)
  • 新しいアコーディオンの中身の高さがページ下部の高さを超える場合は、画面(描画領域)の高さから中身の要素の画面(描画領域)に表示されている部分だけの高さを引いた分だけ上にスクロールするようにする。
  • 初めに開いたアコーディオンの場合、スクロール調整は行わない。



HTMLは上に書いてあることから順に読み込んでいきます。JavaScriptは読み込むのに時間がかかるので、HTMLの最下部に設置して下さいね。</body>の手前がベストです。
例えばこのJavaScriptを『accordion.js』という名前で保存し、自サーバーに上げた場合は↑のHTMLのように入れておけばOKです。

ついでに、現状だとname属性を付けて排他的アコーディオンを作っても全モダンブラウザで正常に動かないので、その辺も全部JavaScriptに入ってます。だから全モダンブラウザで排他的アコーディオンになってます。
↑のCodePenの結果で見るとあんまり正しく動いてない気がするんですが、うちのサイトのプロフィールの嗜好ページとかギャラリーのMPのとこに入れてる峰不二子とオトコ達リストページとか見ると理想的に動いているので多分大丈夫なはずです。

尚、私がアホなのでJavaScriptにコメントアウトを入れまくってますが、消して文章短くした方がオススメです。


document.addEventListener("DOMContentLoaded", () => {
  document.querySelectorAll(".details").forEach(function (el) {
    const summary = el.querySelector(".summary");
    const accordion = el.querySelector(".accordion");
    
    summary.addEventListener("click", (event) => {
      event.preventDefault();

      const previouslyOpen = document.querySelector(".details[open]");
      const accordionHeight = accordion.offsetHeight;

      if (el.getAttribute("open") !== null) {
        const closingAnim = accordion.animate(closingAnimation(accordion), animTiming);
        closingAnim.onfinish = () => {
          el.removeAttribute("open");
        };
      } else {
        if (!previouslyOpen) {
          el.setAttribute("open", "true");
          const openingAnim = accordion.animate(openingAnimation(accordion), animTiming);
        } else {
          if (previouslyOpen && previouslyOpen !== el) {
            const prevAccordion = previouslyOpen.querySelector(".accordion");
            const closingAnim = prevAccordion.animate(closingAnimation(prevAccordion), animTiming);
            closingAnim.onfinish = () => {
              previouslyOpen.removeAttribute("open");
              adjustScroll(el, accordionHeight);
            };
          } else {
            adjustScroll(el, accordionHeight);
          }
          el.setAttribute("open", "true");
          const openingAnim = accordion.animate(openingAnimation(accordion), animTiming);
        }
      }
    });
  });
});

const animTiming = {
  duration: 300,
  easing: "ease-in-out",
};

const closingAnimation = (accordion) => [
  {
    height: accordion.offsetHeight + "px",
    opacity: 1,
  },
  {
    height: 0,
    opacity: 0,
  },
];

const openingAnimation = (accordion) => [
  {
    height: 0,
    opacity: 0,
  },
  {
    height: accordion.offsetHeight + "px",
    opacity: 1,
  },
];

function adjustScroll(element, accordionHeight) {
  const summaryTop = element.querySelector(".summary").getBoundingClientRect().top + window.scrollY;
  const halfRem = parseFloat(getComputedStyle(document.documentElement).fontSize) * 0.5;
  const newScrollPosition = summaryTop - halfRem;
  const viewportHeight = window.innerHeight;

  if (accordionHeight + newScrollPosition > document.body.scrollHeight) {
    window.scrollTo({
      top: document.body.scrollHeight - viewportHeight,
      behavior: 'smooth'
    });
  } else {
    window.scrollTo({
      top: newScrollPosition,
      behavior: 'smooth'
    });
  }
}
畳む


こんな感じでJavaScript使って、てがろぐの続きを読むを開いて迷子になる問題も対処できないかな~。まぁやり始めると原稿スケジュール狂いそうなので、考えるとしてもスパーク終わってから考えるようにします。笑
【2024/07/15】諸々サイズの記述を修正しました
【2024/02/15 23:03追記】フッターについて加筆修正しました

----


どうも、やらなければならない事があると必ず今しなくて良いことをやるジョーです。こんばんは!
締切まで1ヶ月ないんですが、拍手お礼画面がどうしても気になってきて仕方なくなったので弄ってました。絶対今やることじゃない。

PCから見たら問題ないんですけど、スマホから見た時の名前の入力フォームとURLの入力フォームのレイアウトの絶妙にずれたバランスがずっっっっと気になってたんですよ。
before

けどフォームのレイアウトは直接弄れないので、CSSを弄るだけでどうにかならんかな…と弄り始めたのがスタート。弄り始めるとこれは?これは?と面白くなってちょこちょこ修正をしていきました。

以下、自分用備忘録としてメモしておきます。
今やweb拍手に代わるサービスやプラグインもたくさんあるのですが、それでも私は2005年から20年近くお世話になってるweb拍手が好きなんですよね~。
意外に今でも使われている方もちょこちょこ見かけますので、もし何かヒントになるようでしたらどうぞ。
但し、自己流でどうにかしてるので美しい記述とかではないです。とりあえずどうにかなればいい、という広い気持ちで見て頂ければ…笑



まず始めに
元々全体スタイルシートには下記を記述していました。
body{font-size:1rem; color:#000; overflow-x:hidden;}
table{margin: auto;}
input, select, textarea{font-size: 1rem; background: transparent; border: 1px solid #000; color: #000;}
img{max-width: 100%; height: auto;}


ちなみにviewportはお礼画面のメッセージ本文の方に記述しています。
<meta name="viewport" content="device-width, initial-scale=1, maximum-scale=1">



名前の入力フォームとURLの入力フォーム
PCから見えているレイアウトは問題なかったので、モバイル端末から見えるレイアウトだけをどうにかすればいいな~ということで全体スタイルシートに下記を追記。

@media screen and (max-width:600px){
body, input, select, textarea, td{font-size: 4.375vw;}
input[type=text] {width: 100%;}
}


600px以下の画面のあるデバイスの場合にこのCSSを適用します。600pxはなんとなくです。私の中で「まぁここで切り替わりゃいいかな」ポイント。笑
androidは480px、iOSは320pxくらいのイメージなのでそれぞれで分けたければ更に指定しても良いかもしれません。
フォントサイズももうちょい大きくしたいな、と思っていたのでフォントサイズを『4.375vw』に。

で、入力フォームのサイズを横幅いっぱいとかにすれば自動的に改行されていい感じになるかな、と思ったのでinputの横幅を100%に。
しかし『もっと送る』のボタン要素もinputなんですよね。inputだけで記述を進めるとボタンも反応しておかしなことになります。と言う訳でinput[type=text]で指定。



『もっと送る』ボタン
さっきので「じゃあinput[type=submit]で指定すれば別にボタンも弄れるじゃん」ってことに気付いたのでボタンも弄ります。
全体スタイルシートに下記を追記。

input[type=submit] {
font-size: 1rem; /*文字サイズ*/
font-weight: bold; /*太字*/
display: inline-block; 
border-radius:1rem; /*角丸*/
padding: 0.25rem 2rem; /*枠線と文字の間の余白*/
color: #e85298; /*文字色*/
line-height: 1rem; /*行間*/
transition: .3s; /*オンマウスにした時の変化のスピードをちょっと緩やかにする*/
border: 1px solid #e85298; /* 枠線 */
margin-bottom: 1rem; /*ボタン下のメッセージとの余白*/
}

input[type=submit]:hover { /*オンマウスにした時*/
color: #fff; /*文字色*/
background: #e85298; /*背景色*/
}




メッセージ入力欄
問題はここです。
メッセージ入力欄、つまりtextareaのスタイルは『お礼画面設定の変更』のサイズが直に反映されるし、CSSでやっても上手く強制上書きできないんですよ。だから横幅が弄れないんです!

PCから見てももうちょっと幅広にしたかったし、仕方がないので設定のページで、フォーム横サイズは最大値の600pxを選びます。
…が!なんとスマホで見た時に要素が画面からはみ出すのです。width:autoにしようがbox-sizing:border-boxを指定しようが全くどうにもならないのです。
結論、フォーム横サイズは『300px』にすればどの媒体からもギリギリ要素がはみ出さないな…と結論づいたので『300px』で決定。
textareaの弄りようの無さが本当に悔しいのですが、辛うじて行間だけは弄れたので行間だけ広めに指定。

textarea{line-height: 1.4;}

モバイル端末から見た時はこれだとちょっと広すぎる気がしたので、@media screen and (max-width:600px)の記述の所に下記を追記。

textarea{line-height: 1.2;}



フッター
フッターの広告や最下部の謎の余白のようなもの、この辺り今までスマホで見た時にはみ出していたので気になっていたんですよね。
そんな訳で全体スタイルシートに下記を追記。

div.footer{width: auto;}
div#side01{width: auto;}


最下部の謎の余白のようなものはid="side01"という名前の要素で括られていたので、そこを指定して横幅を指示したら対応しました。
その上に偶にバナー広告が出ます。class="footer"という名前の要素なのですが、それで指示をしてもなぜかバナー広告のサイズは調整されず、要素からはみ出して横スクロールが出てしまいます。
コードを確認したら、468×60サイズでガチガチにサイズ固定の広告が外部のJavaScriptから読み込まれているようで…これがどうしても弄れませんでした。諦めていたんですが、やっぱりスマホから見た時に横スクロールが出るのが嫌だ…と言う事で「モバイル端末から開いた時には隠すようにしてみるか」ということに思いいたります。
@media screen and (max-width:600px)の記述の所に下記を追記。

div.footer{display: none;}

これによって600px以下の画面では表示されなくなりました…が!web拍手公式サイトへのリンクも表示されなくなるので、それは違う…!と悶々としてしまいます…公式サイトへのリンクは表示したいんだ…!!!
600px以上の画面では問題なく表示されるとは言え、これは正直広告隠しに当たるような気がするので問題ありそうだったらすぐ記述を削除します…。



終了
最終的に全体スタイルシートは下記の通りになりました。
尚、1000文字しか打ち込めないので、1文字としてカウントされる改行を可能な限り減らしています。

body{font-size:1rem; color:#000; overflow-x:hidden;}
table{margin: auto;}
input, select, textarea{font-size: 1rem; background:transparent; border: 1px solid #000; color:#000;box-sizing: border-box; padding:0.2rem 0.3rem; margin:0.15rem 0;}
input[type=submit] {font-size:1rem;font-weight: bold; display:inline-block;border-radius:1rem;padding: 0.25rem 2rem;color:#e85298;line-height:1rem;transition:.3s;border:1px solid #e85298;margin-bottom:1rem;}
input[type=submit]:hover {color:#fff; background:#e85298;}
textarea{line-height: 1.4;}
img{max-width: 100%; height: auto;}
div.clap{font-size: 0.9rem;}
div.footer{width: 100%;}
div#side01{width: auto;}

@media screen and (max-width:600px){
body, input, select, textarea, td{font-size: 4.375vw;}
input[type=text] {width: 100%;}
textarea{line-height: 1.2;}
div.footer{display: none;}
}



一応私が確認した限りですが、これで下記の感じで見えてる…はずです…!

▼Win10(Chrome)
PC

▼android(Chrome)
android

▼iOS(safari)
iOS

と言うか2012年9月から変わってないからいい加減お礼絵は更新したいと思ってます…12年前の絵を置き続けている…😂畳む

.

Search this site

Archives