Как ограничить ширину span по фактически занимаемому буквами пространству?

Рейтинг: 0Ответов: 1Опубликовано: 24.04.2023

В span есть стрелочка сортировки, она позиционируется абсолютно относительно span. Но когда происходит перенос строки, то образуется промежуток между тестом span и стрелочкой. Мне нужно, чтобы span занимал ширину по факту, сколько занимается ширины тест (чтобы не было промежутка). Есть ли такая возможность?

введите сюда описание изображения

const CriteriaSelector: React.FC<ICriteriaSelectorProps> = ({
  label,
  sortCriteria,
  sortHook,
  className,
}) => {
  return (
    <div
      className={classNames(styles.criteriaSelector, className)}
      onClick={() => sortHook.recountSort(sortCriteria)}
    >
      <span
        className={classNames(
          styles.label,
          sortCriteria === sortHook.sortCriteria && styles.active
        )}
      >
        {label}
        {sortHook.sortMode != ESortMode.noSort &&
          sortCriteria === sortHook.sortCriteria && (
            <svg
              className={classNames(
                styles.arrow,
                sortHook.sortMode === ESortMode.ascendingOrder &&
                  styles.arrow_reverse
              )}
              viewBox="0 0 8 6"
              fill="none"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
                fill="#606773"
              />
            </svg>
          )}
      </span>
    </div>
  );
};
.criteriaSelector {
  position: relative;
  cursor: pointer;
  user-select: none;
  max-width: 200px;


  .label {
    position: relative;
    display: inline-block;

    .arrow {
      position: absolute;
      aspect-ratio: 1.333 / 1;
      width: 8px;
      left: calc(100% + 8px);
      top: 50%;
      transform: translateY(-50%);
      transition: transform 150ms ease;

      @include breakpoint(sm) {
        left: calc(100% + 2px);
        width: 7px;
      }

      &_reverse {
        transform: translateY(-50%) scale(1, -1);
      }
    }
  }

Ответы

▲ 0

Я ровным счетом ничего с Вашим кодом не делал, кроме преобразования его под ванильные HTML и CSS таким образом видно, что в Firefox не воспроизводит проблему.

введите сюда описание изображения

.criteriaSelector {
  position: relative;
  cursor: pointer;
  user-select: none;
  max-width: 200px;
}
.criteriaSelector .label {
  position: relative;
  display: inline-block;
}
.criteriaSelector .arrow {
  position: absolute;
  aspect-ratio: 1.333;
  width: 8px;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  transition: transform 150ms ease;
}
.criteriaSelector .arrow_reverse {
  transform: translateY(-50%) scale(1, -1);
}
<div class="criteriaSelector">
  <span class="label active">
    <a href="#">Транспорт, дата и время возврата в г.Новосибирск</a>
    <svg
      class="arrow arrow_reverse"
      viewBox="0 0 8 6"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
    <path
      d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
      fill="#606773"
    />
    </svg>
  </span>
</div>
<br>
<div class="criteriaSelector">
  <span class="label active">
    Транспорт, дата и время возврата в г.Новосибирск
    <svg
      class="arrow"
      viewBox="0 0 8 6"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
    <path
      d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
      fill="#606773"
    />
    </svg>
  </span>
</div>

Решение для Chrome пока предварительное с добавлением свойства width cо значением min-content:

введите сюда описание изображения

.criteriaSelector {
  position: relative;
  cursor: pointer;
  user-select: none;
  max-width: 200px;
}
.criteriaSelector .label {
  position: relative;
  display: inline-block;
  width: min-content;
}
.criteriaSelector .arrow {
  position: absolute;
  aspect-ratio: 1.333;
  width: 8px;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  transition: transform 150ms ease;
}
.criteriaSelector .arrow_reverse {
  transform: translateY(-50%) scale(1, -1);
}
<div class="criteriaSelector">
  <span class="label active">
    <a href="#">Транспорт, дата и время возврата в г.Новосибирск</a>
    <svg
      class="arrow arrow_reverse"
      viewBox="0 0 8 6"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
    <path
      d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
      fill="#606773"
    />
    </svg>
  </span>
</div>
<br>
<div class="criteriaSelector">
  <span class="label active">
    Транспорт, дата и время возврата в г.Новосибирск
    <svg
      class="arrow"
      viewBox="0 0 8 6"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
    <path
      d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
      fill="#606773"
    />
    </svg>
  </span>
</div>

Если задать еще и min-width например со значением 175px можно добиться желаемого результата, но этот вариант не всегда гарантирует такое поведение (с другим текстом может быть иначе)

введите сюда описание изображения

В качестве дополнительного варианта решения этой задачи можно воспользоваться функцией вставки неразрывных пробелов

В Вашем конкретном случае использование будет таким:

{textUpdate(label)}

function textUpdate(text){
  const symb = String.fromCharCode(160) // &nbsp
  const widthLine = 35 // ширина надписи в символах
  const indexes = Array.from(text.matchAll(/ /g))
    .map(e => e.index).filter(e => e < widthLine)
  return = text.slice(0, indexes.slice(-1))
    .replace(/ /g, symb) + text.slice(indexes.slice(-1)) 
}

let el = document.querySelector('.label.active a')
el.textContent =  textUpdate(el.textContent)
.criteriaSelector {
  position: relative;
  cursor: pointer;
  user-select: none;
  max-width: 200px;
}
.criteriaSelector .label {
  position: relative;
  display: inline-block;
}
.criteriaSelector .arrow {
  position: absolute;
  aspect-ratio: 1.333;
  width: 8px;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  transition: transform 150ms ease;
}
.criteriaSelector .arrow_reverse {
  transform: translateY(-50%) scale(1, -1);
}
<div class="criteriaSelector">
  <span class="label active">
    <a href="#">Транспорт, дата и время возврата в г.Новосибирск</a>
    <svg
      class="arrow arrow_reverse"
      viewBox="0 0 8 6"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
    >
    <path
      d="M4 6L0.535898 6.52533e-07L7.4641 4.68497e-08L4 6Z"
      fill="#606773"
    />
    </svg>
  </span>
</div>