AMP
  • 網站

星級評分

簡介

這個星級評分小工具僅使用 CSS 實作,考量到 AMP 對於自訂 JavaScript 的限制。它仍然具備星級評分元件的關鍵功能

  • 觸控、滑鼠和鍵盤可存取性

  • 當使用者將滑鼠游標移到星星上方時,星星會變色

  • 一旦做出選擇,就會「固定」

  • 清晰可縮放的向量圖示

  • 螢幕閱讀器友善

設定

匯入 amp-form 元件。

<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>

我們也需要 amp-mustache 元件。

<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>

星級評分的 CSS

這個星級評分實作將「☆」Unicode 字元精確地覆蓋在單選按鈕之上。下方的內嵌註解詳細說明了規則。

<style amp-custom>
  .rating {
    --star-size: 3;  /* use CSS variables to calculate dependent dimensions later */
    padding: 0;  /* to prevent flicker when mousing over padding */
    border: none;  /* to prevent flicker when mousing over border */
    unicode-bidi: bidi-override; direction: rtl;  /* for CSS-only style change on hover */
    text-align: left;  /* revert the RTL direction */
    user-select: none;  /* disable mouse/touch selection */
    font-size: 3em;  /* fallback - IE doesn't support CSS variables */
    font-size: calc(var(--star-size) * 1em);  /* because `var(--star-size)em` would be too good to be true */
    cursor: pointer;
    /* disable touch feedback on cursor: pointer - http://stackoverflow.com/q/25704650/1269037 */
    -webkit-tap-highlight-color: rgba(0,0,0,0);
    -webkit-tap-highlight-color: transparent;
    margin-bottom: 1em;
  }
  /* the stars */
  .rating > label {
    display: inline-block;
    position: relative;
    width: 1.1em;  /* magic number to overlap the radio buttons on top of the stars */
    width: calc(var(--star-size) / 3 * 1.1em);
  }
  .rating > *:hover,
  .rating > *:hover ~ label,
  .rating:not(:hover) > input:checked ~ label {
    color: transparent;  /* reveal the contour/white star from the HTML markup */
    cursor: inherit;  /* avoid a cursor transition from arrow/pointer to text selection */
  }
  .rating > *:hover:before,
  .rating > *:hover ~ label:before,
  .rating:not(:hover) > input:checked ~ label:before {
    content: "★";
    position: absolute;
    left: 0;
    color: gold;
  }
  .rating > input {
    position: relative;
    transform: scale(3);  /* make the radio buttons big; they don't inherit font-size */
    transform: scale(var(--star-size));
    /* the magic numbers below correlate with the font-size */
    top: -0.5em;  /* margin-top doesn't work */
    top: calc(var(--star-size) / 6 * -1em);
    margin-left: -2.5em;  /* overlap the radio buttons exactly under the stars */
    margin-left: calc(var(--star-size) / 6 * -5em);
    z-index: 2;  /* bring the button above the stars so it captures touches/clicks */
    opacity: 0;  /* comment to see where the radio buttons are */
    font-size: initial; /* reset to default */
  }
  form.amp-form-submit-error [submit-error] {
    color: red;
  }
</style>

用法

雖然這個星級評分小工具可透過鍵盤存取,但並非沒有問題

  • 點擊/輕觸小工具,然後按下向上/向下/向左/向右箭頭。遺憾的是,在 Firefox 和 Safari 中,鍵盤箭頭會反向運作。這個問題在非 Chrome 瀏覽器上似乎無法修正,除非使用 JavaScript,因此請持續關注 amp-rating 元件。
  • 將滑鼠游標移到星星上方,即可看到樣式變化。

我們將使用一組單選按鈕來接收使用者對於星級評分的輸入,因為它們可透過鍵盤存取。對於桌面版,當使用者將滑鼠游標懸停在星星上方時,變更先前星星的樣式會很不錯。《唯一》純 CSS 方式可在滑鼠懸停時影響先前元素的樣式,方法是以反向 DOM 順序列出它們,這就是為什麼下方的 <input> 元素從 5 排列到 1。

我們希望表單在使用者做出選擇後立即提交,而無需「提交」按鈕。為此,我們將 inputon 屬性設定為在 change 時提交表單。

初始評分取決於哪個單選按鈕設定了 checked 屬性。這是選填項目。

<form id="rating" method="post" action-xhr="https://amp.dev.org.tw/documentation/examples/interactivity-dynamic-content/star_rating/set" target="_blank">
  <fieldset class="rating">
    <input name="rating" type="radio" id="rating5" value="5" on="change:rating.submit">
    <label for="rating5" title="5 stars"></label>

    <input name="rating" type="radio" id="rating4" value="4" on="change:rating.submit">
    <label for="rating4" title="4 stars"></label>

    <input name="rating" type="radio" id="rating3" value="3" on="change:rating.submit">
    <label for="rating3" title="3 stars"></label>

    <input name="rating" type="radio" id="rating2" value="2" on="change:rating.submit" checked="checked">
    <label for="rating2" title="2 stars"></label>

    <input name="rating" type="radio" id="rating1" value="1" on="change:rating.submit">
    <label for="rating1" title="1 stars"></label>
  </fieldset>
  <div submit-success>
    <template type="amp-mustache">
      <p>Thanks for rating {{rating}} star(s)!</p>
    </template>
  </div>
  <div submit-error>
    <template type="amp-mustache">
      Looks like something went wrong. Please try to rate again. {{error}}
    </template>
  </div>
</form>
需要更多說明嗎?

如果本頁面的說明未能涵蓋您的所有問題,請隨時與其他 AMP 使用者聯繫,討論您的確切使用案例。

前往 Stack Overflow
未說明的特色功能?

AMP 專案大力鼓勵您的參與和貢獻!我們希望您能成為我們開放原始碼社群的長期參與者,但我們也歡迎您針對您特別熱衷的問題做出一次性貢獻。

在 GitHub 上編輯範例