Skip to content

Commit dd184f3

Browse files
authored
Merge pull request #10 from EDITD/add-docs
Add docs
2 parents 4ea42c0 + 2a1b3e1 commit dd184f3

File tree

5 files changed

+279
-43
lines changed

5 files changed

+279
-43
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Changelog
2+
3+
## v1.0.0
4+
- First public release

CONTRIBUTING.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Contributing
2+
3+
We are open to, and grateful for, any contributions made by the community.
4+
5+
## Reporting Issues
6+
7+
Before opening an issue, please search the [issue tracker](https://github.com/EDITD/react-responsive-picture/issues) to make sure your issue hasn't already been reported.
8+
9+
## Development
10+
11+
Visit the [Issue tracker](https://github.com/EDITD/react-responsive-picture/issues) to find a list of open issues that need attention.
12+
13+
Fork, then clone the repo:
14+
```
15+
git clone https://github.com/your-username/react-responsive-picture.git
16+
```
17+
18+
Build package for dev mode. It will automatically watch any changes in `src/` forlder:
19+
```
20+
yarn run dev
21+
```
22+
23+
We follow [eslint-config-edited](https://www.npmjs.com/package/eslint-config-edited) for code style.
24+
25+
### Building and testing
26+
27+
Build package:
28+
```
29+
yarn run build
30+
```
31+
32+
To run the tests:
33+
```
34+
npm run test
35+
```
36+
37+
To perform linting with `eslint`, run the following:
38+
```
39+
npm run lint
40+
```
41+
42+
### New Features
43+
44+
Please open an issue with a proposal for a new feature or refactoring before starting on the work. We don't want you to waste your efforts on a pull request that we won't want to accept.
45+
46+
## Submitting Changes
47+
48+
* Open a new issue in the [Issue tracker](https://github.com/EDITD/react-responsive-picture/issues).
49+
* Fork the repo.
50+
* Create a new feature branch based off the `master` branch.
51+
* Make sure all tests pass and there are no linting errors.
52+
* Submit a pull request, referencing any issues it addresses.
53+
54+
Please try to keep your pull request focused in scope and avoid including unrelated commits.
55+
56+
After you have submitted your pull request, we'll try to get back to you as soon as possible. We may suggest some changes or improvements.
57+
58+
Thank you for contributing!

README.md

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,161 @@
1-
# react-responsive-picture
2-
A future-proof responsive image component that supports latest Picture specification
1+
## react-responsive-picture
2+
3+
A future-proof responsive image component that supports latest `<picture>` specification. Uses [picturefill](https://github.com/scottjehl/picturefill) for backward compatibility from IE9+.
4+
5+
---
6+
7+
## Installation
8+
9+
`npm install react-responsive-picture` || `yarn add react-responsive-picture`
10+
11+
## How to use
12+
13+
### Code
14+
15+
```jsx
16+
import { Picture } from 'react-responsive-picture';
17+
18+
class App extends Component {
19+
render() {
20+
return (
21+
<Picture
22+
sources = {[
23+
{
24+
srcSet: "path-to-mobile-image.jpg, path-to-mobile-image@2x.jpg 2x",
25+
media: "(max-width: 420px)",
26+
},
27+
{
28+
srcSet: "path-to-desktop-image.jpg 1x, path-to-desktop-image@2x.jpg 2x",
29+
},
30+
{
31+
srcSet: "path-to-desktop-image.webp",
32+
type: "image/webp"
33+
}
34+
]}
35+
/>
36+
);
37+
};
38+
}
39+
```
40+
41+
### Props
42+
43+
| Prop | Type | Default | Definition |
44+
| --- | --- | --- | --- |
45+
| sources | array | | The array of source objects. Check Sources section for more information. |
46+
| src | string | (transparent pixel) | Source for standalone/fallback image. To prevent issues in some browsers, by default `src` is set to a 1x1 transparent pixel data image. |
47+
| sizes | string | | Sizes attribute to be used with `src` for determing best image for user's viewport. |
48+
| alt | string | | Alternative text for image |
49+
| className | string | | Any additional CSS classes you might want to use to style the image |
50+
| style | object \|\| array | | Any additional styles you might want to send to the wrapper. Uses glamor to process it so you can send either objects or arrays. |
51+
52+
## Examples
53+
54+
### Simple image
55+
Normal `<img>` like behaviour. The same image is displayed on every device/viewport.
56+
57+
```jsx
58+
<Picture src="path-to-image.jpg" />
59+
```
60+
61+
will render:
62+
63+
```html
64+
<img srcset="path-to-image.jpg" />
65+
```
66+
67+
### Image with different resolutions
68+
Different images for specific devices (usually retina).
69+
70+
```jsx
71+
<Picture src="path-to-image@2x.png 2x, path-to-image.png 1x" />
72+
```
73+
74+
will render:
75+
76+
```html
77+
<img srcset="path-to-image@2x.png 2x, path-to-image.png 1x" />
78+
```
79+
80+
### Image with sizes
81+
When you want to let the browser determine the best image for user's current viewport. More information about `size` attribute on this great [blog post](http://ericportis.com/posts/2014/srcset-sizes/).
82+
83+
```jsx
84+
<Picture
85+
src="large.jpg 1024w, medium.jpg 640w, small.jpg 320w"
86+
sizes="(min-width: 36em) 33.3vw, 100vw"
87+
/>
88+
```
89+
90+
will render:
91+
92+
```html
93+
<img srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" />
94+
```
95+
96+
### Image with art direction
97+
When you want to explicitly control which image is displayed at specific viewport sizes.
98+
99+
```jsx
100+
<Picture
101+
sources = {[
102+
{
103+
srcSet: "path-to-mobile-image.jpg, path-to-mobile-image@2x.jpg 2x",
104+
media: "(max-width: 420px)",
105+
},
106+
{
107+
srcSet: "path-to-desktop-image.jpg 1x, path-to-desktop-image@2x.jpg 2x",
108+
},
109+
{
110+
srcSet: "path-to-desktop-image.webp",
111+
type: "image/webp"
112+
}
113+
]}
114+
/>
115+
```
116+
117+
will render:
118+
119+
```html
120+
<picture>
121+
<source srcset="path-to-mobile-image.jpg, path-to-mobile-image@2x.jpg 2x" media="(max-width: 420px)">
122+
<source srcset="path-to-desktop-image.jpg 1x, path-to-desktop-image@2x.jpg 2x">
123+
<source srcset="path-to-desktop-image.webp" type="image/webp">
124+
<img srcset="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" />
125+
</picture>
126+
```
127+
128+
The `sources` prop is where you can determine the behaviour of the `<Picture>` component and which images will show for the specific screens.
129+
130+
For each source you can send an object containing `srcSet`, `media` and `type` although the last two are optional.
131+
132+
### Utilities
133+
134+
There's also a `<FullsizePicture>` component that you can use to display full-size images using the same benefits of `<Picture>` for art direction.
135+
136+
```jsx
137+
<div style={{ height: 200 }}>
138+
<FullsizePicture
139+
sources = {[
140+
{
141+
srcSet: "path-to-mobile-image.jpg, path-to-mobile-image@2x.jpg 2x",
142+
media: "(max-width: 420px)",
143+
},
144+
{
145+
srcSet: "path-to-desktop-image.jpg 1x, path-to-desktop-image@2x.jpg 2x",
146+
},
147+
]}
148+
/>
149+
</div>
150+
```
151+
152+
It will automatically fill the entire parent element maintaining the original image ratio. Please not that the parent element needs to have a defined height as you would expect for any background image as well.
153+
154+
## Contributing
155+
156+
Please follow our [contributing guidelines](https://github.com/EDITD/react-responsive-picture/blob/master/CONTRIBUTING.md).
157+
158+
## License
159+
160+
[MIT](https://github.com/EDITD/react-responsive-picture/blob/master/LICENSE)
161+

src/components/FullsizePicture.jsx

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class FullSizePicture extends React.PureComponent {
77
const styles = {
88
overflow: "hidden",
99
width: "100%",
10+
height: "100%",
1011
position: "relative",
1112
};
1213

@@ -19,27 +20,24 @@ class FullSizePicture extends React.PureComponent {
1920
getImageWrapperStyles() {
2021
return css({
2122
position: "absolute",
22-
top: 0,
23-
bottom: 0,
24-
left: 0,
25-
right: 0,
23+
top: "-50%",
24+
width: "200%",
25+
left: "-50%",
26+
height: "200%",
2627
});
2728
}
2829

2930
getImageStyles() {
30-
return css({
31+
return {
3132
position: "absolute",
32-
top: "50%",
33-
left: "50%",
33+
top: 0,
34+
left: 0,
35+
bottom: 0,
36+
right: 0,
3437
margin: "auto",
35-
width: "auto",
36-
height: "auto",
37-
minWidth: "100%",
38-
minHeight: "100%",
39-
maxWidth: "none",
40-
maxHeight: "none",
41-
transform: "translate3d(-50%, -50%, 0)",
42-
});
38+
minWidth: "50%",
39+
minHeight: "50%",
40+
};
4341
}
4442

4543
render() {
@@ -50,7 +48,7 @@ class FullSizePicture extends React.PureComponent {
5048
alt={this.props.alt}
5149
src={this.props.src}
5250
sources={this.props.sources}
53-
{...this.getImageStyles()}
51+
style={this.getImageStyles()}
5452
/>
5553
</div>
5654
</div>

src/components/Picture.jsx

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,51 +15,67 @@ class Picture extends React.PureComponent {
1515
const ieVersion = document.documentMode ? document.documentMode : -1;
1616
const { sources } = this.props;
1717

18-
if (!sources) {
18+
if (sources == null) {
1919
return null;
2020
}
2121

22-
const mappedSources = sources.map((source, index) => (
23-
<source
24-
key={index}
25-
srcSet={source.srcSet}
26-
media={source.media}
27-
/>
28-
));
22+
const mappedSources = sources.map((source, index) => {
23+
if (source.srcSet == null) {
24+
return null;
25+
}
26+
27+
return (
28+
<source
29+
key={index}
30+
srcSet={source.srcSet}
31+
media={source.media}
32+
type={source.type}
33+
/>
34+
);
35+
});
2936

3037
// IE9 requires the sources to be wrapped around an <audio> tag.
3138
if (ieVersion === 9) {
3239
return (
33-
<audio>
40+
<video style={{ display: "none" }}>
3441
{mappedSources}
35-
</audio>
42+
</video>
3643
);
3744
}
3845

3946
return mappedSources;
4047
}
4148

42-
render() {
49+
renderImage(skipSizes = false) {
50+
// Adds sizes props if sources isn't defined
51+
const sizesProp = skipSizes ? null : { sizes: this.props.sizes };
4352
return (
44-
<picture>
45-
{this.renderSources()}
46-
<img
47-
alt={this.props.alt}
48-
src={this.props.src}
49-
width={this.props.width}
50-
height={this.props.height}
51-
className={this.props.className}
52-
data-no-retina={true}
53-
{...this.getImageStyles()}
54-
/>
55-
</picture>
53+
<img
54+
alt={this.props.alt}
55+
srcSet={this.props.src}
56+
className={this.props.className}
57+
data-no-retina={true}
58+
{...sizesProp}
59+
{...this.getImageStyles()}
60+
/>
5661
);
5762
}
63+
64+
render() {
65+
if (this.props.sources != null) {
66+
return (
67+
<picture>
68+
{this.renderSources()}
69+
{this.renderImage(true)}
70+
</picture>
71+
);
72+
}
73+
74+
return this.renderImage();
75+
}
5876
}
5977

6078
Picture.propTypes = {
61-
width: React.PropTypes.number,
62-
height: React.PropTypes.number,
6379
sources: React.PropTypes.array,
6480
src: React.PropTypes.string.isRequired,
6581
style: React.PropTypes.oneOfType([
@@ -68,6 +84,7 @@ Picture.propTypes = {
6884
]),
6985
alt: React.PropTypes.string,
7086
className: React.PropTypes.string,
87+
sizes: React.PropTypes.string,
7188
};
7289

7390
Picture.defaultProps = {

0 commit comments

Comments
 (0)