Skip to content

Commit

Permalink
feat: support non-zero body margins
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed Jan 21, 2019
1 parent aad1025 commit 0828cf6
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 31 deletions.
20 changes: 10 additions & 10 deletions example/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ export default class App extends Component <{}, AppState> {
const gapMode = 'margin';
return (
<AppWrapper>
{this.state.counter && <RemoveScrollBar gapMode={gapMode}/>}
<div style={{
position: 'absolute',
left: 0,
right: 0,
top: 0,
height: '50px',
backgroundColor: '#F00'
}}>floating
</div>
{this.state.counter ? <RemoveScrollBar/> : undefined}
{/*<div style={{*/}
{/*position: 'absolute',*/}
{/*left: 0,*/}
{/*right: 0,*/}
{/*top: 0,*/}
{/*height: '50px',*/}
{/*backgroundColor: '#F00'*/}
{/*}}>floating*/}
{/*</div>*/}

<div
style={{
Expand Down
2 changes: 1 addition & 1 deletion example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<title>Example</title>
<style>
body {
margin: 0;
/*margin: 10px;*/
}
</style>
</head>
Expand Down
29 changes: 16 additions & 13 deletions src/component.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import {styleSinglentone} from 'react-style-singleton';
import {GapMode, getGapWidth} from './utils';
import {GapMode, GapOffset, getGapWidth, zeroGap} from './utils';

export interface BodyScroll {
noRelative?: boolean;
Expand All @@ -10,21 +10,28 @@ export interface BodyScroll {
}

export interface BodyState {
gap: number
gap: GapOffset;
};

const Style = styleSinglentone();

// important tip - once we measure scrollBar width and remove them
// we could not repeat this operation
// thus we are using style-singleton - only the first "yet correct" style will be applied.
const getStyles = (gap: number, allowRelative: boolean, gapMode: GapMode = 'margin', important: string) => `
const getStyles = ({left, top, right, gap}: GapOffset, allowRelative: boolean, gapMode: GapMode = 'margin', important: string) => `
body {
overflow: hidden ${important};
${
[
allowRelative && `position: relative ${important};`,
gapMode == 'margin' && `margin-right: ${gap}px ${important};`,
gapMode == 'margin' && `
padding-left: ${left}px;
padding-top: ${top}px;
padding-right: ${right}px;
margin-left:0;
margin-top:0;
margin-right: ${gap}px ${important};
`,
gapMode == 'padding' && `padding-right: ${gap}px ${important};`,
].filter(Boolean).join('')
}
Expand Down Expand Up @@ -77,9 +84,7 @@ export class RemoveScrollBar extends React.Component<BodyScroll, BodyState> {
if (!this.state.gap) {
const gap = getGapWidth(this.props.gapMode);
if (gap !== this.state.gap) {
this.setState({
gap
})
this.setState({gap})
}
}
}
Expand All @@ -88,19 +93,17 @@ export class RemoveScrollBar extends React.Component<BodyScroll, BodyState> {
this.forceUpdate();
if (this.state.gap && this.props.dynamic) {
if (window.innerHeight > document.body.offsetHeight) {
// reset state to reevaluate
this.setState({
gap: 0
})
// reset state to re-evaluate
this.setState({gap: zeroGap})
}
}
};

render() {
const {noRelative, noImportant, gapMode} = this.props;
const {noRelative, noImportant, gapMode = 'margin'} = this.props;
const {gap} = this.state;

return gap
return gap.gap
? <Style styles={getStyles(gap, !noRelative, gapMode, !noImportant ? "!important" : '')}/>
: null;
}
Expand Down
39 changes: 32 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,42 @@
export type GapMode = 'padding' | 'margin';

const getOffset = (gapMode: GapMode) => {
export interface GapOffset {
left: number;
top: number;
right: number;
gap: number;
}

export const zeroGap = {
left: 0,
top: 0,
right: 0,
gap: 0,
};

const getOffset = (gapMode: GapMode): number[] => {
const cs = window.getComputedStyle(document.body);
const value = cs[gapMode === 'padding' ? 'paddingRight' : 'marginRight'];
return parseInt(value || '', 10) || 0;
const left = cs[gapMode === 'padding' ? 'paddingLeft' : 'marginLeft'];
const top = cs[gapMode === 'padding' ? 'paddingTop' : 'marginTop'];
const right = cs[gapMode === 'padding' ? 'paddingRight' : 'marginRight'];
return [
parseInt(left || '', 10) || 0,
parseInt(top || '', 10) || 0,
parseInt(right || '', 10) || 0
];
};

export const getGapWidth = (gapMode: GapMode = 'margin') => {
export const getGapWidth = (gapMode: GapMode = 'margin'): GapOffset => {
if (typeof window === 'undefined') {
return 0;
return zeroGap;
}
const currentOffset = getOffset(gapMode);
const offsets = getOffset(gapMode);
const documentWidth = document.documentElement.clientWidth;
const windowWidth = window.innerWidth;
return Math.max(0, windowWidth - documentWidth + currentOffset);
return {
left: offsets[0],
top: offsets[1],
right: offsets[2],
gap: Math.max(0, windowWidth - documentWidth + offsets[2] - offsets[0]),
}
};

0 comments on commit 0828cf6

Please sign in to comment.