측면 항목의 너비가 다른 경우 중간 항목을 중앙에 유지


162

여기에 이미지 설명을 입력하십시오

점이 상자 사이의 공간을 나타내는 다음 레이아웃을 상상해보십시오.

[Left box]......[Center box]......[Right box]

오른쪽 상자를 제거해도 가운데 상자가 여전히 가운데에있는 것을 좋아합니다.

[Left box]......[Center box].................

왼쪽 상자를 제거해도 마찬가지입니다.

................[Center box].................

이제 가운데 상자의 내용이 길어지면 가운데에 남아있는 동안 필요한만큼 사용 가능한 공간을 차지하게됩니다. 어떤 공간이 남아되지 않는 곳 때 왼쪽과 오른쪽 상자에 따라서 축소 결코 것 overflow:hiddentext-overflow: ellipsis내용을 깰 효과가 올 것이다;

[Left box][Center boxxxxxxxxxxxxx][Right box]

위의 모든 것이 이상적인 상황이지만이 효과를 얻는 방법을 모릅니다. 내가 플렉스 구조를 만들 때 이렇게 :

.parent {
    display : flex; // flex box
    justify-content : space-between; // horizontal alignment
    align-content   : center; // vertical alignment
}

왼쪽과 오른쪽 상자가 정확히 같은 크기라면 원하는 효과를 얻습니다. 그러나 둘 중 하나의 크기가 다른 경우 중앙 박스가 더 이상 중앙에 배치되지 않습니다.

나를 도울 수있는 사람이 있습니까?

최신 정보

A justify-self는 좋을 것입니다. 이상적입니다.

.leftBox {
     justify-self : flex-start;
}

.rightBox {
    justify-self : flex-end;
}

3
기본적으로 ... 당신은 할 수 없습니다. 그것이 flexbox작동 하는 방식 이 아닙니다 . 다른 방법론을 시도 할 수 있습니다.
Paulie_D

1
Flexbox가 제대로 완료되면 실제로 완료 할 것입니다. flexbox는 공간을 분배하고 아이템이 어떻게 동작하는지에 관한 것입니다.
Mark

1
우리는 justify-self오늘 앞에서 논의
Michael Benjamin

답변:


130

왼쪽 및 오른쪽 상자의 크기가 정확히 같은 경우 원하는 효과를 얻습니다. 그러나 둘 중 하나의 크기가 다른 경우 중앙 박스가 더 이상 중앙에 배치되지 않습니다. 나를 도울 수있는 사람이 있습니까?

다음은 형제의 너비에 관계없이 flexbox를 사용하여 중간 항목을 중앙에 배치하는 방법입니다.

주요 특징들:

  • 순수한 CSS
  • 절대 포지셔닝 없음
  • JS / jQuery 없음

중첩 된 플렉스 컨테이너와 auto여백을 사용하십시오 .

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}

.box:first-child > span { margin-right: auto; }

.box:last-child  > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
p {
  text-align: center;
  margin: 5px 0 0 0;
}
<div class="container">
  <div class="box"><span>short text</span></div>
  <div class="box"><span>centered text</span></div>
  <div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>&#8593;<br>true center</p>

작동 방식은 다음과 같습니다.

  • 최상위 div ( .container)는 플렉스 컨테이너입니다.
  • 각 자식 div ( .box)는 이제 플렉스 항목입니다.
  • 컨테이너 공간을 균등하게 분배하기 위해 각 .box항목이 제공 flex: 1됩니다 ( 자세한 내용 참조 ).
  • 이제 항목이 행의 모든 ​​공간을 소비하고 너비가 같습니다.
  • 각 항목을 (중첩) 플렉스 컨테이너로 만들고를 추가하십시오 justify-content: center.
  • 이제 각 span요소는 중심 플렉스 아이템입니다.
  • 플렉스 auto마진을 사용 하여 바깥 쪽을 span좌우 로 이동하십시오 .

또한 여백을 독점적으로 버리고 justify-content사용할 수 있습니다 auto.

그러나 여백이 항상 우선 justify-content하기 때문에 여기서 작동 할 수 있습니다 auto.

8.1. auto 여백 정렬

를 통해 정렬하기 이전 justify-content하고 align-self, 양의 여유 공간은 해당 차원에서 자동 마진에 배포됩니다.


5
이 솔루션은 width지정할 수 없습니다
Alex G

@AlexG, 어떻게? 예를 들어 줄 수 있습니까?
Michael Benjamin

4
공간을 분배하기 위해 구부러진 요소의 너비를 변경하면 OP의 문제가 완전히 사라집니다. 그들의 질문은 요소들 사이에 공간이 있습니다. 예 : "점들이 상자 사이의 공간을 나타내는 다음 레이아웃을 상상해보십시오." 균등 한 크기의 요소 3 개로 텍스트를 맞추는 것은 쉽지 않습니다.
Leland

1
맹세 컨데 지금 바로 키스 할 수 있습니다! 이것이 바로 내가 필요로했던 것입니다.
eliotRosewater

1
이것은 MacOS 스타일의 창 제목 표시 줄을 구현하는 데 필요한 것을 정확하게 수행했습니다. white-space: nowrap영역이 너무 작아지면 텍스트가 줄 바꿈되는 것을 방지하기 위해 퍼즐의 마지막 부분이 추가 되었습니다.
Geo1088

32
  1. 용기에 3 개의 플렉스 품목 사용
  2. flex: 1첫 번째와 마지막으로 설정하십시오 . 이것은 그들이 남은 공간을 채우기 위해 동일하게 성장하게합니다.
  3. 따라서 가운데 ​​부분은 중앙에 위치하는 경향이 있습니다.
  4. 그러나 첫 번째 또는 마지막 항목의 내용이 넓은 경우 새로운 min-width: auto초기 값 으로 인해 해당 플렉스 항목도 커 집니다.

    참고 Chrome은이를 제대로 구현하지 않는 것 같습니다. 그러나, 당신은 설정할 수 min-width-webkit-max-content또는 -webkit-min-content그것도 작동합니다.

  5. 이 경우에만 가운데 요소가 가운데에서 밀려납니다.

.outer-wrapper {
  display: flex;
}
.item {
  background: lime;
  margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
  flex: 1;
  display: flex;
  min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
  justify-content: flex-end;
}
.animate {
  animation: anim 5s infinite alternate;
}
@keyframes anim {
  from { min-width: 0 }
  to { min-width: 100vw; }
}
<div class="outer-wrapper">
  <div class="left inner-wrapper">
    <div class="item animate">Left</div>
  </div>
  <div class="center inner-wrapper">
    <div class="item">Center</div>
  </div>
  <div class="right inner-wrapper">
    <div class="item">Right</div>
  </div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>


감사합니다.이 답변은 수락 된 답변과 달리 OPs 질문에 성공적으로 답변합니다.
Blowsie

8

flexbox를 사용하는 것을 기본값으로 사용하는 대신 grid를 사용하면 최상위 하위 항목에 추가 마크 업없이 2 줄의 CSS로 해결할 수 있습니다.

HTML :

<header class="header">
  <div class="left">variable content</div>
  <div class="middle">variable content</div>
  <div class="right">variable content which happens to be very long</div>
</header>

CSS :

.header {
  display: grid;
  grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
  /* use either */
  margin: 0 auto;
  /* or */
  text-align: center;
}

Flexbox는 흔들리지 만 모든 것에 대한 답이되어서는 안됩니다. 이 경우 그리드가 가장 깨끗한 옵션입니다.

https://codepen.io/anon/pen/mooQOV : 테스트의 즐거움을 위해 코드 펜을 만들었습니다.


2
flex모든 것 이외의 다른 옵션이 있음을 인정하기 위해 +1 . 내 유일한 반대는 align-items: center아이템의 높이가 다르고 정렬이 필요한 경우 flex ( )를 사용하여 수직 정렬이 더 쉬워진다는 것입니다.
Felipe

1
이 솔루션 과이 문제에 그리드를 사용하는 아이디어가 마음에 들지만 솔루션에는 몇 가지 단점이 있다고 생각합니다. 먼저 외부 셀 내용 중 하나가 20 %보다 크면 내용이 랩핑되거나 중앙 셀로 넘치게됩니다. 둘째, 중심이 60 %보다 크면 컨텐츠 상자 바깥으로 자라서 마지막 셀을 감싸거나 밀어냅니다. 마지막으로, 중심은 바깥 쪽 셀을위한 공간을 만들기 위해 이동하지 않습니다. 단지 랩 / 오버 플로우를 강요합니다. 나쁜 해결책은 아니지만 IMO는 "분명히 가장 깨끗한 옵션"이 아닙니다.
Chris

6

이렇게 할 수 있습니다 :

.bar {
    display: flex;    
    background: #B0BEC5;
}
.l {
    width: 50%;
    flex-shrink: 1;
    display: flex;
}
.l-content {
    background: #9C27B0;
}
.m { 
    flex-shrink: 0;
}
.m-content {    
    text-align: center;
    background: #2196F3;
}
.r {
    width: 50%;
    flex-shrink: 1;
    display: flex;
    flex-direction: row-reverse;
}
.r-content { 
    background: #E91E63;
}
<div class="bar">
    <div class="l">
        <div class="l-content">This is really long content.  More content.  So much content.</div>
    </div>
    <div class="m">
        <div class="m-content">This will always be in the center.</div>
    </div>
    <div class="r">
        <div class="r-content">This is short.</div>
    </div>
</div>


2

다음은 flexbox 대신 grid를 사용하는 답변입니다. 이 솔루션에는 허용되는 답변처럼 HTML에 추가 손자 요소가 필요하지 않습니다. 2019의 그리드 답변과 달리 한쪽의 내용이 중앙으로 넘칠 정도로 길어지면 올바르게 작동합니다.

이 솔루션에서하지 않는 한 가지는 질문에 설명 된대로 줄임표를 표시하거나 가운데 상자에 추가 내용을 숨기는 것입니다.

section {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}

section > *:last-child {
  white-space: nowrap;
  text-align: right;
}

/* not essential; just for demo purposes */
section {
  background-color: #eee;
  font-family: helvetica, arial;
  font-size: 10pt;
  padding: 4px;
}

section > * {
  border: 1px solid #bbb;
  padding: 2px;
}
<section>
  <div>left</div>
  <div>center</div>
  <div>right side is longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer</div>
</section>

<section>
  <div>left</div>
  <div>center</div>
  <div>right side is much, much longer, super long in fact</div>
</section>


1

display: flex부모와 자녀를 사용하는 또 다른 방법은 다음과 같습니다 .

.Layout{
    display: flex;
    justify-content: center;
}
.Left{
    display: flex;
    justify-content: flex-start;
    width: 100%;
}
.Right{
    display: flex;
    justify-content: flex-end;
    width: 100%;
}
<div class = 'Layout'>
    <div class = 'Left'>I'm on the left</div>
    <div class = 'Mid'>Centered</div>
    <div class = 'Right'>I'm on the right</div>
</div>


0

이 간단한 방법을 사용하여 중간 요소의 정확한 중심 정렬에 도달 할 수도 있습니다.

.container {
    display: flex;
    justify-content: space-between;
}

.container .sibling {
    display: flex;
    align-items: center;
    height: 50px;
    background-color: gray;
}

.container .sibling:first-child {
    width: 50%;
    display: flex;
    justify-content: space-between;
}

.container .sibling:last-child {
    justify-content: flex-end;
    width: 50%;
    box-sizing: border-box;
    padding-left: 100px; /* .center's width divided by 2 */
}

.container .sibling:last-child .content {
    text-align: right;
}

.container .sibling .center {
    height: 100%;
    width: 200px;
    background-color: lightgreen;
    transform: translateX(50%);
}

코드 펜 : https://codepen.io/ErAz7/pen/mdeBKLG

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.