やりたいこと・お悩み
メインのコンテンツのボリュームが少ない時に、footer の下の余白を消したい。少ない時は下にくっついていて、多い時は押し出されてほしい。
解決策は、flex
なり grid
なりを使ってやる。
やったんだけど、余白が消えなかった。html/css
だけだとうまくいくのに、なんで?!
html/css
的な解決策(一般論)
<html>
<head>...</head>
<body>
<header>header</header>
<main>main</main>
<footer>footer</footer>
<body>
</html>
なる html に対し、css を書いていく。
flex
の場合
body {
display: flex;
flex-flow: column;
min-height: 100vh;
}
main {
flex-grow: 1;
}
grid
の場合
body {
display: grid;
grid-template-rows: auto 1fr auto;
grid-template-columns: 100%;
min-height: 100vh;
}
flex か grid は、どっちでも良いんじゃないかと。1次元のレイアウトだし、flex で良いかなー。
うまくいかない理由
body に style を当てているから。親違い。
前述の html
のつもりで書いたものは、react 上では、実際には、以下のようになる。
<html>
<head>...</head>
<body>
<div id="root">
<header>header</header>
<main>main</main>
<footer>footer</footer>
</div>
<body>
</html>
<div id="root" />
犯人はこいつだ! body
の中に要素が1つしかないので、flex
も grid
も効かない。
解決方法
body
ではなく、#root
にスタイルを当てるか、別途 div
で囲んで、それに当てる。
#root
にスタイルを当てるのは、何となく抵抗があったので、div
でラップしてそれに当てる。
元のレイアウトテンプレート
layout.tsx
import { ReactNode, FC } from 'react';
import { Footer } from '../../organisms/layouts/Footer';
import { Header } from '../../organisms/layouts/Header';
type Props = {
children: ReactNode;
};
export const Layout: FC<Props> = (props) => {
const { children } = props;
return (
<>
<Header />
<main>{children}</main>
<Footer />
</>
);
};
これを、私は emotion を使っているので、
layout.tsx
/** @jsxImportSource @emotion/react */
import { ReactNode, FC } from 'react';
import { css } from '@emotion/react';
import { Footer } from '../../organisms/layouts/Footer';
import { Header } from '../../organisms/layouts/Header';
type Props = {
children: ReactNode;
};
export const Layout: FC<Props> = (props) => {
const { children } = props;
const wrapper = css`
display: flex;
flex-flow: columns;
min-height: 100vh;
main {
flex-grow: 1;
}
`;
return (
<div css={wrapper}>
<Header />
<main>{children}</main>
<Footer />
</div>
);
};
そして、元々 body に当てていたものは、消す。body > div#root > div.wrapper
となんだかなーって気もするし、異なるレイアウトを使う時などに、同じことを書くことになるかも知れないが、App.tsx
に書くのも違う気がするので、これで。<></>
も嫌いだし。
以上、CSS 小ネタでした。