플렉스 전환 : 내용에 맞게 늘이기 (또는 축소)


9

선택한 div를 확장하고 나머지 공간에 맞게 동일하게 확장하여 다른 div를 적절하게 작동시킬 수있는 스크립트 (여기서는 사용자의 도움으로)를 코딩했습니다 (너비가 고정 된 첫 번째 제외).

그리고 여기 내가 달성하고자하는 그림이 있습니다.

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

이를 위해 플렉스와 전환을 사용합니다.

잘 작동하지만 jQuery 스크립트는 "400 %"스트레치 값을 지정합니다 (테스트에 적합 함).

이제 선택한 div를 "400 %"고정 값 대신 내용에 정확히 맞게 확장 / 축소하고 싶습니다.

어떻게 할 수 있을지 모르겠습니다.

가능합니까?

div를 복제하고 내용에 맞추고 값을 얻은 다음이 값을 사용하여 전환했지만 초기 너비는 백분율이지만 목표 값은 픽셀입니다. 작동하지 않습니다.

픽셀 값을 백분율로 변환하면 결과가 어떤 이유로 든 내용에 정확하게 맞지 않습니다.

모든 경우에, 이것은 어쨌든 내가 원하는 것을 달성하는 약간 복잡한 방법으로 보입니다.

선택한 div의 내용에 맞게 전환 할 수있는 flex 속성이 없습니까?

코드는 다음과 같습니다 ( 더 나은 읽기를 위해 편집 / 간단 화됨 ).

var expanded = '';

$(document).on("click", ".div:not(:first-child)", function(e) {

  var thisInd =$(this).index();
  
  if(expanded != thisInd) {
    //fit clicked fluid div to its content and reset the other fluid divs 
    $(this).css("width", "400%");
    $('.div').not(':first').not(this).css("width", "100%");
    expanded = thisInd;
  } else {
    //reset all fluid divs
    $('.div').not(':first').css("width", "100%");
    expanded = '';
  }
});
.wrapper {
  overflow: hidden;
  width: 100%;
  margin-top: 20px;
  border: 1px solid black;
  display: flex;
  justify-content: flex-start;
}

.div {
  overflow: hidden;
  white-space: nowrap;
  border-right: 1px solid black;
  text-align:center;
}

.div:first-child {
  min-width: 36px;
  background: #999;
}

.div:not(:first-child) {
  width: 100%;
  transition: width 1s;
}

.div:not(:first-child) span {
  background: #ddd;
}

.div:last-child {
  border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Click on the div you want to fit/reset (except the first div)

<div class="wrapper">

  <div class="div"><span>Fixed</span></div>
  <div class="div"><span>Fluid (long long long long long text)</span></div>
  <div class="div"><span>Fluid</span></div>
  <div class="div"><span>Fluid</span></div>

</div>

jsfiddle은 다음과 같습니다.

https://jsfiddle.net/zajsLrxp/1/

편집 : 여기 당신의 도움으로 작업 솔루션이 있습니다 (창 크기 조정 + div 수와 첫 번째 열의 너비가 동적으로 계산되어 업데이트 됨).

var tableWidth;
var expanded	   = '';
var fixedDivWidth  = 0;
var flexPercentage = 100/($('.column').length-1);

$(document).ready(function() {

    // Set width of first fixed column
    $('.column:first-child .cell .fit').each(function() {
        var tempFixedDivWidth = $(this)[0].getBoundingClientRect().width;
        if( tempFixedDivWidth > fixedDivWidth ){fixedDivWidth = tempFixedDivWidth;}
    });
    $('.column:first-child'  ).css('min-width',fixedDivWidth+'px')
	
    //Reset all fluid columns
    $('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')
})

$(window).resize( function() {

    //Reset all fluid columns
    $('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')	
    expanded   = '';
})

$(document).on("click", ".column:not(:first-child)", function(e) {
	
    var thisInd =$(this).index();	
	
    // if first click on a fluid column
    if(expanded != thisInd) 
    {
        var fitDivWidth=0;
    
        // Set width of selected fluid column
        $(this).find('.fit').each(function() {
            var c = $(this)[0].getBoundingClientRect().width;
            if( c > fitDivWidth ){fitDivWidth = c;}
        });
        tableWidth = $('.mainTable')[0].getBoundingClientRect().width; 
        $(this).css('flex','0 0 '+ 100/(tableWidth/fitDivWidth) +'%')
		
        // Use remaining space equally for all other fluid column
        $('.column').not(':first').not(this).css('flex','1 1 '+flexPercentage+'%')
		
        expanded = thisInd;
    }

    // if second click on a fluid column
    else
    {
        //Reset all fluid columns
        $('.column').not(':first').css('flex','1 1 '+flexPercentage+'%')

        expanded = '';
    }
  
});
body{
    font-family: 'Arial';
    font-size: 12px;
    padding: 20px;
}

.mainTable {
    overflow: hidden;
    width: 100%;
    border: 1px solid black;
    display: flex;
    margin-top : 20px;
}

.cell{
    height: 32px;
    border-top: 1px solid black;
    white-space: nowrap;
}

.cell:first-child{
    background: #ccc;
    border-top: none;
}

.column {
    border-right: 1px solid black;
    transition: flex 0.4s;
    overflow: hidden;
    line-height: 32px;
    text-align: center;
}

.column:first-child {
    background: #ccc;
}

.column:last-child {
  border-right: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<span class="text">Click on the header div you want to fit/reset (except the first one which is fixed)</span>

<div class="mainTable">
    <div class="column">
        <div class="cell"><span class="fit">Propriété</span></div>
        <div class="cell"><span class="fit">Artisan 45</span></div>
        <div class="cell"><span class="fit">Waterloo 528</span></div>	    
    </div>
		  
    <div class="column">	    
        <div class="cell"><span class="fit">Adresse</span></div>
        <div class="cell"><span class="fit">Rue du puit n° 45 (E2)</span></div>
        <div class="cell"><span class="fit">Chaussée de Waterloo n° 528 (E1)</span></div>	    
    </div>
		
    <div class="column">	    
        <div class="cell"><span class="fit">Commune</span></div>
        <div class="cell"><span class="fit">Ixelles</span></div>
        <div class="cell"><span class="fit">Watermael-Boitsfort</span></div>	    
    </div>
		    
    <div class="column">	    
        <div class="cell"><span class="fit">Ville</span></div>
        <div class="cell"><span class="fit">Marche-en-Famenne</span></div>
        <div class="cell"><span class="fit">Bruxelles</span></div>	    
    </div>
		  
    <div class="column">
        <div class="cell"><span class="fit">Surface</span></div>
        <div class="cell"><span class="fit">120 m<sup>2</sup></span></div>
        <div class="cell"><span class="fit">350 m<sup>2</sup></span></div>	    
    </div>
</div>

그리고 다음은 직장에서 본격적인 예입니다 (스타일 + 패딩 + 더 많은 데이터).

https://jsfiddle.net/zrqLowx0/2/

모두 감사합니다 !


1
이 모든 것 이후에 만든 것을 보여주는 질문에 최종 결과 를 추가 할 수있을만큼 친절 하십시오. 나는 그것이 어떻게 보이는지에 정말로 관심이 있습니다. 감사! (... 어떻게 사용되는지에 대한 통찰력이 있을까요? ...)
Rene van der Lende

좋아, 모든 불필요한 요소에서 스크립트를 청소하자마자 그렇게 할 것입니다 (몇 분 안에 추측합니다). 즉, 어떻게해야합니까? Azametzin의 답변이 완벽하게 되더라도 원본 게시물을 편집하고 이에 대한 테이크를 추가합니까? 나는 몇 가지 사항을 변경하지만 90 % 동일합니다. (하지만 보여
드리게되어 기쁩니다

요점은 다음과 같습니다. 저는 일종의 Excel 스프레드 시트를 에뮬레이트하고 사람들이 내용에 맞게 특정 열을 클릭 할 수 있기를 바랍니다. 일반적으로 테이블은 수행하지만 원하는 방식으로 열 크기를 조정할 때 열이 올바르게 작동하지 않습니다 (한 번에 한 열을 쉽게 확장 할 수 있지만 나머지 공간을 차지하기 위해 다른 열을 실시간으로 수행하기는 어렵습니다) flex는 div를 위해 할 것입니다. table 또는 dataTable을 사용하지 않는 다른 이유가 있지만이 게시물의 범위를 벗어납니다.
Bachir Messaouri 1

1
쉽게 '편집'을 누르고 질문의 끝으로 가서 새로운 스 니펫 (모두 포함)을 포함하여 유능한 숙고를 추가하십시오. '새 독자'에게는 방해가되지 않고 기본적으로 '스 니펫 숨기기'(왼쪽 아래 확인란)를 숨기십시오. 내 첫 번째 생각은 당신이 멋진 '하모니카'와 같은 위젯, 아이콘 및 모두에 사용할 것이라고 생각했습니다. 스프레드 시트 허, 나는 여기에 논의 된 것과 동일한 원칙을 사용하여 위 / 아래 / 왼쪽 / 오른쪽으로 모든 화면을 확장하는 전체 화면을 가지고 있습니다 (관심있는 경우).
레네 반 데르 렌데

2
최종 결과를 게시하면서 여분의 마일을 보냈습니다. 훨씬 더 보람있는 질문에 답변합니다! Cudos ...
르네 반 데르 Lende

답변:


4

max-width및 을 사용하여 해결할 수 calc()있습니다.

첫째, 대신 width: 100%flex: 1그들은이 경우에는 더있는 성장 있도록, CSS에있는 div에 대한. 또한에 전환을 사용하십시오 max-width.

이제 관련 값을 저장해야합니다.

  • 이 경우 애니메이션 될 div의 양 ( divsLength가변)-3입니다.
  • 이 경우 고정 div 및 테두리 ( extraSpace변수)에 사용 된 총 너비는 39px입니다.

이 두 변수를 사용하면 모든 div에 기본값 max-width( defaultMaxWidth변수)을 설정 하고 나중에 사용할 수 있습니다. 이것이 전세계에 저장되는 이유입니다.

defaultMaxWidth것입니다 calc((100% - extraSpace)/divsLength).

이제 클릭 기능을 입력하겠습니다 :

div를 확장하기 위해 대상 텍스트의 너비가 호출 된 변수에 저장되고 사용 textWidth중인 div 에 부동 소수점 값을 반환 max-width.하므로 적용됩니다 .getBoundingClientRect().width.

나머지 div의 경우 적용 할 calc()for div가 만들어 max-width집니다.
입니다 : calc(100% - textWidth - extraScape)/(divsLength - 1).
계산 된 결과는 나머지 각 div의 너비입니다.

확장 된 div를 클릭하면, 즉 정상으로 돌아가려면 기본값 max-width이 모든 .div요소 에 다시 적용됩니다 .

var expanded = false,
    divs = $(".div:not(:first-child)"),
    divsLength = divs.length,
    extraSpace = 39, //fixed width + border-right widths 
    defaultMaxWidth = "calc((100% - " + extraSpace + "px)/" + divsLength + ")";

    divs.css("max-width", defaultMaxWidth);

$(document).on("click", ".div:not(:first-child)", function (e) {
  var thisInd = $(this).index();

  if (expanded !== thisInd) {
    
    var textWidth = $(this).find('span')[0].getBoundingClientRect().width;  
    var restWidth = "calc((100% - " + textWidth + "px - " + extraSpace + "px)/" + (divsLength - 1) + ")";
    
    //fit clicked fluid div to its content and reset the other fluid divs 
    $(this).css({ "max-width": textWidth });
    $('.div').not(':first').not(this).css({ "max-width": restWidth });
    expanded = thisInd;
  } else {
    //reset all fluid divs
    $('.div').not(':first').css("max-width", defaultMaxWidth);
    expanded = false;
  }
});
.wrapper {
  overflow: hidden;
  width: 100%;
  margin-top: 20px;
  border: 1px solid black;
  display: flex;
  justify-content: flex-start;
}

.div {
  overflow: hidden;
  white-space: nowrap;
  border-right: 1px solid black;
  text-align:center;
}

.div:first-child {
  min-width: 36px;
  background: #999;
}

.div:not(:first-child) {
  flex: 1;
  transition: max-width 1s;
}

.div:not(:first-child) span {
  background: #ddd;
}

.div:last-child {
  border-right: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

Click on the div you want to fit/reset (except the first div)

<div class="wrapper">

  <div class="div"><span>Fixed</span></div>
  <div class="div"><span>Fluid (long long long long text)</span></div>
  <div class="div"><span>Fluid</span></div>
  <div class="div"><span>Fluid</span></div>

</div>

이 방법은 동적으로 작동하며 모든 해상도에서 작동해야합니다.
하드 코딩에 필요한 유일한 값은 extraSpace변수입니다.


1
예, 이는 정확한 계산과 flexbox 축소 효과에 대한 이해가 필요한 문제입니다. 아직 "완벽한"솔루션이 없지만 앞으로 다시 시도하고 싶습니다. 그래서 다른 방법으로 질문을 북마크에 추가하여 올바르게 수행하는 방법을 알아 내려고했습니다. 좋은 도전입니다.
Azametzin

1
참고로, 코드를보다 쉽게 ​​읽고 테스트 할 수 있도록 코드를 편집했습니다. 나는 좋은 추가 범위를 추가했습니다. 최대 너비 전환을 추가하지는 않았지만 지금까지는 효과가 없었습니다.
Bachir Messaouri

1
멋있는. 방금 해결했습니다. 답변을 편집 중입니다.
Azametzin

1
좋은! 내가 어쨌든 몇 시간 동안 외출 할 때 시간을내어 ;-)
Bachir Messaouri

1
방금 편집 한 댓글을 보았습니다 (업데이트 댓글이 필요함). getBoundingClientRect () 사용은 매우 영리하며 나에게 발생하지 않았습니다 (39 픽셀 고정 너비를 고려하는 것과 동일). Windows 크기와 Fluid div에서 작동하는지 확인하기 위해 조금 더 테스트 할 것입니다. 너에게 다시 돌아갈 게. 대단히 감사합니다! 추신 : 귀하의 솔루션은 어떤 이유로 든 jQuery 3.3.1에서는 작동하지만 3.4.1에서는 작동하지 않습니다.
Bachir Messaouri

3

너비 또는 계산 함수를 처리해야합니다. Flexbox에는 솔루션이 있습니다.

모든 div를 (첫 번째가 아닌) 동일하게 만들기 위해을 사용 flex: 1 1 auto합니다.

<div class="wrapper">
  <div class="div"><span>Fixed</span></div>
  <div class="div"><span>Fluid (long long long long text)</span></div>
  <div class="div"><span>Fluid</span></div>
  <div class="div"><span>Fluid</span></div>
</div>

일반 div 및 선택한 div에 대한 플렉스 규칙을 정의하십시오. transition: flex 1s;당신의 친구입니다. 선택된 것을 위해 우리는 flex 성장을 필요로하지 않기 때문에 flex: 0 0 auto;

.wrapper {
  width: 100%;
  margin-top: 20px;
  border: 1px solid black;
  display: flex;
}

.div {
  white-space: nowrap;
  border-right: 1px solid black;
  transition: flex 1s;
  flex: 1 1 auto;
}

.div.selected{
  flex: 0 0 auto;
}

.div:first-child {
  min-width: 50px;
  background: #999;
  text-align: center;
}

.div:not(:first-child) {
  text-align: center;
}

.div:last-child {
  border-right: 0px;
}

div:not(:first-child) span {
  background: #ddd;
}

사용자가 div를 클릭 할 때마다 선택한 클래스를 추가하십시오. 또한 두 번째 클릭에 대해 전환을 사용하여 선택한 항목을지도에 저장하고 선택한 여러 항목을 표시 할 수 있습니다 (물론이 코드 예제는 제외).

$(document).on("click", ".div:not(:first-child)", function(e) {
  const expanded = $('.selected');
  $(this).addClass("selected");
  if (expanded) {
    expanded.removeClass("selected");
  }
});

https://jsfiddle.net/f3ao8xcj/


감사합니다. 내가 원하는 것과 반대의 행동을 취하기 때문에 귀하의 사례를 연구해야하며 아직 그것을 뒤집는 방법을 모르겠습니다 (아마도 사소한 것일 수도 있습니다). 기본적으로 모든 유동 div가 동일하게 커지기를 원합니다. 이 내용이 내용에 맞는 것을 클릭 할 때만 (그리고 다른 유체 div는 나머지 공간을 똑같이 공유합니다). 그리고 같은 div를 두 번 클릭하면 모든 Fluid div가 재설정되어 내용에 대한 걱정없이 공간을 다시 공유합니다. 내가 실수하지 않으면, 당신이 한 것과 정반대입니다. 어떻게 그것을 뒤집을 지 아직 확실하지 않습니다.
Bachir Messaouri

그러나 이것이 되돌릴 수 있다면 CSS 너비 속성을 엉망으로 만들 필요가 없으므로 솔루션이 얼마나 우아하고 간단합니다. Flex는 이것을 내부적으로 처리하는 것 같습니다. 즉, 직감이있어 반대 방향으로 달성하기가 더 어려울 것입니다. 기다려 봐 후속 감사합니다.
Bachir Messaouri

1
@BachirMessaouri 다시 아주 간단합니다. 업데이트 된 버전을 참조하십시오.
허리케인

나는 당신의 대본의 우아함을 좋아하지만 귀하의 솔루션은 나의 요청의 일부만을 고려합니다. 내 요청은 내용을 맞추는 것뿐만 아니라 유체 div를 클릭하기 전, 도중 및 후에 남은 공간을 똑같이 공유하는 것입니다. 당신의 스크립트는 전혀 그렇지 않다면 그것을 잘 해결하지 못합니다. 그리고 그것이 모든 것을 두뇌 버너로 만드는 것입니다. 내 필요를 매우 명확하게하기 위해 원본 게시물에 사진을 추가했습니다. 위의 다른 스크립트는 정확히 전달하지 못하는 곳에서 시작됩니다. 이상하게도 두 스크립트가 혼합되어 작동하는 것 같습니다. 테스트 중이며 일단 완료되면 다시 연락 드리겠습니다.
Bachir Messaouri

@BachirMessaouri 여기서 빠진 것은 아무도 귀하의 사례에 완벽한 솔루션을 제공 할 필요가 없다는 것입니다. Flex transition: Stretch (or shrink) to fit content질문 제목이며이 답변은 간단한 방법입니다. 귀하의 사례에 대한 해결책을 찾는 것은 귀하의 책임입니다.
허리케인

2

몇 가지 시험판을 사용한 후에는 이것이 가장 짧고 가장 확실한 솔루션 인 것 같습니다.

기본적으로 필요로하는 모든 IS가 인 flexbox는 스트레칭이 수행 할 <div>기본적으로 한계에 요소를하지만 때 <span>클릭,의 스트레칭을 제약 조건 <div><span>폭 ...

의사 코드 :

when <span> clicked and already toggled then <div> max-width = 100%, reset <span> toggle state

otherwise <div> max-width = <span> width, set <span> toggle state

CSS를 '관련 메커니즘'과 '눈 사탕 만'섹션으로 나누면 쉽게 읽을 수 있습니다 (코드 리사이클링).

코드에 많은 주석이 달렸으므로 여기에 많은 텍스트가 없습니다 ...

Quirk 에서 로 transition전환 할 때에 추가 지연 이 있습니다. Chrome, Edge, IE11 및 Firefox (모두 W10) 에서이 동작을 확인했으며 모두이 기발한 것으로 보입니다. 일부 브라우저 내부 재 계산이 진행되거나 시간이 두 번 사용됩니다 ( '느낌'). 이상하게도, 추가 지연이 없습니다.divmax-width: 100%max-width = span widthtransition

그러나 짧은 전환 시간 (예 : 현재 사용중인 150ms) 으로이 추가 지연은 눈에 띄지 않습니다. (또 다른 질문에 대한 좋은 하나 ...)

최신 정보

다른 모든 것을 재설정하는 새 버전 <div>. 나는 진지한 점을 정말로 싫어하지만 Flexbox 스트레칭과 transition가치 때문입니다. 없이 transition더 볼 점프 없습니다. 어떤 것이 효과가 있는지 시험 해봐야합니다.

나는 document.querySelectorAll()자바 스크립트 코드 에만 추가 했습니다.


제안 해 주셔서 감사합니다. 유동 div를 클릭하면 잘 맞지 만 나머지 두 공간은 동등하게 확장되지 않으므로 나머지 요구 사항에 맞지 않습니다 (그러나 아주 좋은 시작점입니다). 어느 것이 문제의 50 %입니다. 그리고 네,이 기발함도 있습니다. Azametzin의 스크립트는 별다른 문제없이 100 % 일을합니다. 나는 그의 스크립트와 최대 너비 대신에 플렉스 전환을 사용하여 매력처럼 작동했습니다. 당신의 도움을 주셔서 대단히 감사합니다 !
Bachir Messaouri 1

@Azametzin s '의 비고 :이 사가에는 정말 재미있는 날이었습니다. :). 다음에 이미지로 시작할까요?
레네 반 데르 렌데

확인. 나는 설명이 충분하다고 생각했지만 분명히 틀렸다. 그래도 이미지는 어제부터 있습니다. 그러나 나는 당신의 요점을 얻는다. 몇 분 만에 사용자 정의 스크립트를 표시하도록 원본 메시지를 편집하겠습니다. 대단히 감사합니다!
Bachir Messaouri

사용자 정의 솔루션으로 업데이트 된 원본 게시물!
Bachir Messaouri
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.