搜尋

首頁  >  問答  >  主體

居中文字和圖示的按鈕

<p>我正在開發一個帶有圖標和文字的按鈕元件。 </p> <p>圖示位於按鈕的左側,文字在按鈕中間對齊。 </p> <p>如果文字無法適應按鈕,它不應該換行,而是可以被截斷。 </p> <p>截斷文字的關鍵條件是,文字距離按鈕邊緣的距離應與圖示距離按鈕邊緣的距離相同。 </p> <p>所以你不能在按鈕中加入相等的內嵌填滿。 </p> <p>如果文字沒有被截斷,它將在按鈕中間對齊。 </p> <p>然而,一旦它開始重疊圖標或無法適應按鈕,文字將被截斷。 </p> <p>換句話說,在正常狀態下,圖示的位置不變,但當文字沒有足夠的空間時,圖示會將文字推到被截斷的位置。 </p> <p>按鈕的視覺化範例</p> <p>我嘗試使用CSS來實現這個效果,但失敗了。 </p> <p>最後,我為每個按鈕添加了一個ResizeObserver,用於計算文字是否有足夠的空間。 </p> <p>如果沒有足夠的空間,將套用不同的樣式到圖示上。 </p> <p>我的ResizeObserver解決方案,請嘗試調整視窗大小</p> <p>CodePen</p> <pre class="brush:php;toolbar:false;">const CLASS_TEXT = `button__text`; const CLASS_NO_FREE_SPACE = `button_no-free-space`; const FREE_SPACE_SIZE = 70; const buttons = document.querySelectorAll(`.${CLASS_ROOT}`); const handleButtonResize = (entries) => { entries.forEach((entry) => { const { target } = entry; const text = target.querySelector(`.${CLASS_TEXT}`); const { width: widthButton } = entry.contentRect; if (!(text instanceof HTMLElement)) { return; } const widthText = text.offsetWidth; const freeSpaceLeft = (widthButton - widthText) / 2; const noFreeSpace = freeSpaceLeft <= FREE_SPACE_SIZE; target.classList.toggle(CLASS_NO_FREE_SPACE, noFreeSpace); }); }; const resizeObserver = new ResizeObserver(handleButtonResize); [...buttons].forEach((button) => { resizeObserver.observe(button); });</pre> <p><strong>我的問題是:</strong></p> <p>是否可以使用純CSS實現相同的效果? </p>
P粉033429162P粉033429162468 天前513

全部回覆(1)我來回復

  • P粉615886660

    P粉6158866602023-08-16 09:08:45

    由於圖示的寬度始終相同(2em),我們可以使用::after偽元素作為右側空間平衡的「緩衝區」。

    .button__icon設定為彈性佈局流。這在「推動」其他元素時至關重要。給它margin-right來平衡按鈕的左填充。

    建立一個具有flex-basis: calc(2em 20px)::after偽元素。其中2em.button__icon的寬度,20px.button__iconmargin-right。這樣可以在.button__text較短時平衡左右空間。

    justify-content: space-between套用到父元素,以幫助平衡.button__icon.button__text::after.button__text較短時。

    加上flex-shrink: 999,一個巨大的收縮因子,以便佈局引擎在.button__text較長時優先收縮::after元素。

    *,
    *::before,
    *::after {
      box-sizing: border-box;
    }
    
    body {
      padding: 20px;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
    }
    
    .grid {
      display: grid;
      grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 20px;
      margin: auto 0;
    }
    
    .button {
      position: relative;
      display: flex;
      justify-content: space-between;
      align-items: center;
      cursor: pointer;
      outline: none;
      border: 1px solid #808080;
      padding: 20px;
      width: 100%;
      background-color: transparent;
      min-height: 80px;
    }
    
    .button::before {
      content: "";
      width: 1px;
      position: absolute;
      top: 0;
      left: 50%;
      bottom: 0;
      background-color: red;
    }
    
    .button::after {
      flex: 0 999 calc(2em + 20px);
      content: "";
    }
    
    .button__icon {
      flex-shrink: 0;
      margin-right: 20px;
    }
    
    .button__text {
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      min-width: 0;
      text-align: center;
      border: 1px solid blue;
    }
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"/>
    
    <div class="grid">
      <button class="button">
        <i class="fa-solid fa-heart fa-2xl button__icon"></i>
       
        <span class="button__text">
          长文本,应该被截断
        </span>
      </button>
    
      <button class="button">
        <i class="fa-solid fa-thumbs-up fa-2xl button__icon"></i>
       
        <span class="button__text">
          中等长度
        </span>
      </button>
    
      <button class="button">
        <i class="fa-solid fa-house fa-2xl button__icon"></i>
       
        <span class="button__text">
          短
        </span>
      </button>
    </div>

    回覆
    0
  • 取消回覆