본문 바로가기

오늘의 커밋

2020.11.10 오늘의 커밋. React에서 Bottom이 Fixed일때 화면 크기에 따라 스크롤 자동 생성, 겹침 발생하지 않도록 처리.

728x90

오전에 간단하게 처리하려고 했던 내용입니다.

 

 

 

프론트앤드 개발자 단톡방에 물어봤던 내용.

 

 

 

 

현재 위 앱은 아이폰5나 아이폰se1과 같이 매우 작은 해상도의 스마트폰에서는 footer영역과 main 영역이 겹치는 문제가 있었습니다.

 

 

이유는

footer의 css가 아래와 같이 되어있기 때문이었죠.

 

footer {

  width100%;

  positionabsolute;

  bottom0;

  text-aligncenter;

  colorwhite;

  background#80808030;

}  

 

위치가 고정이므로, dom에서 스크롤을 생성하기 위한 공간을 차지하지 않습니다.

 

구글링해보면 저와 같은 고민을 했던 개발자의 질문이 있죠

(검색 키워드 : footer position fixed overlap)

stackoverflow.com/questions/18990675/css-footer-overlapping-content-other-glitches

 

CSS: Footer overlapping content, other glitches

I've looked around for similar issues here and in other places, but I can't seem to find a definitive answer. When I add enough text to a page that it would get to the footer, the footer simply ove...

stackoverflow.com

위 내용처럼

 

position:static 혹은 relative로 설정할 경우, 정상적으로 스크롤이 생깁니다.

 

하지만 저는 공간이 남는 경우에는 바닥에 딱 붙이고,

공간이 부족한 경우에만 relative로 처리하고싶습니다.

 

아마 대다수의 사람들이 그렇게 되길 원하겠죠.

 

정리하자면 요건은 다음과 같습니다.

1. 화면에 공간이 충분한 경우에는 footer에 position:absolute 성을 준다

2. 화면에 공간이 부족한 경우에는 footer에 position:relative성을 준다

3. 화면에서 어떠한 동작으로 인해 공간이 부족해지는 경우에 동적으로 스타일을 변경한다. 

 

이것입니다.

 

React에서는 화면이 새로 render 될때마다 호출되는 함수 componentDidUpdate가 존재합니다.

이를 이용해 아래와 같이 구현할 수 있습니다.

 

//1. 생성자에서 state 정의하기
    constructor(props) {
        super(props);
        this.state = {
            footerStyle :{},	//스타일
            changeFlag :true    //변경 플래그
        }
    }

//2. 컴포넌트 변경시점마다 setAuthHeight 함수 호출
    componentDidUpdate(prevProps) {
        if(this.state.changeFlag){
            this.setAutoHeight()
        }
    }


//3. 현재 화면 크기를 계산하여 스크롤이 필요한 경우 css를 변경하는 함수
    setAutoHeight(){
        let footer = {}
        if(document.getElementsByTagName("main").length !=0 && document.getElementsByTagName("footer").length !=0 && window.innerHeight < document.getElementsByTagName("main")[0].offsetHeight + document.getElementsByTagName("footer")[0].offsetHeight){
            footer =  {"position": "relative","marginTop": "10px"}
        }
        this.setState({footerStyle:footer})
        this.setState({changeFlag:false})
    }

//4. 실질적으로 컴포넌트를 변경시키는 함수
    updateComponent = async (idx,index,rIdx) => { //대충 Component가 변경되는 함수
		//대충 Component가 변경된다는 내용
		this.setState({ newsList: newTranslateList });
        this.setState({changeFlag:true})
    }

//5. style에 state을 전달
<footer style={this.state.footerStyle}>
	<div>대충 푸터의 내용들</div>
</footer>

 

우선 당연하지만 생성자에 상태값을 추가해줍니다.

 

그다음, 컴포넌트를 변경할때마다 setAutoHeight 함수를 호출합니다. 단, state가 변할때마다 호출되면 함수가 끝없이 호출되므로, changeFlag가 true일때만 호출하도록 합니다.

 

화면을 변경시키는 요인에 changeFlag를 넣어주면 사용자가 의도한 동작에 대해서만 autoHeight를 할 수 있게됩니다.

 

세번째, 현재 화면의 높이를 스크립트로 계산하고, main과 footer의 높이 합이 이보다 크다면 css를 변경합니다.

이때, 변경 완료 후 changeFlag를 false로 하여 setAutoHeight가 다시 호출되지 않도록 막습니다.

 

네번째, 실질적인 화면에 영향을 주는 동작 다음에 changeFlag를 true로 변경해줍니다.

해당 동작 이후 화면이 변경되면 autoHeight를 1회 호출할 것입니다.

 

마지막으로 footer에 style을 state와 연결해줍니다.

state가 변경되면, 자동으로 css가 변경될 것입니다.

 

 

 

 

 

오전에 해결하고자 했는데 생각보다 오래 걸렸네요.

728x90