├── .gitignore
├── README.md
├── build
├── asset-manifest.json
├── favicon.ico
├── fonts
│ ├── redacted-regular.eot
│ ├── redacted-regular.svg
│ ├── redacted-regular.ttf
│ ├── redacted-regular.woff
│ ├── redacted-regular.woff2
│ ├── redacted-script-bold.eot
│ ├── redacted-script-bold.svg
│ ├── redacted-script-bold.ttf
│ ├── redacted-script-bold.woff
│ ├── redacted-script-bold.woff2
│ ├── redacted-script-light.eot
│ ├── redacted-script-light.svg
│ ├── redacted-script-light.ttf
│ ├── redacted-script-light.woff
│ ├── redacted-script-light.woff2
│ ├── redacted-script-regular.eot
│ ├── redacted-script-regular.svg
│ ├── redacted-script-regular.ttf
│ ├── redacted-script-regular.woff
│ ├── redacted-script-regular.woff2
│ └── stylesheet.css
├── index.html
├── manifest.json
├── problem-css-masonry.png
├── service-worker.js
└── static
│ ├── css
│ └── main.2e4c670b.css
│ └── js
│ ├── main.0a863532.js
│ └── main.0a863532.js.map
├── package.json
├── public
├── favicon.ico
├── fonts
│ ├── redacted-regular.eot
│ ├── redacted-regular.svg
│ ├── redacted-regular.ttf
│ ├── redacted-regular.woff
│ ├── redacted-regular.woff2
│ ├── redacted-script-bold.eot
│ ├── redacted-script-bold.svg
│ ├── redacted-script-bold.ttf
│ ├── redacted-script-bold.woff
│ ├── redacted-script-bold.woff2
│ ├── redacted-script-light.eot
│ ├── redacted-script-light.svg
│ ├── redacted-script-light.ttf
│ ├── redacted-script-light.woff
│ ├── redacted-script-light.woff2
│ ├── redacted-script-regular.eot
│ ├── redacted-script-regular.svg
│ ├── redacted-script-regular.ttf
│ ├── redacted-script-regular.woff
│ ├── redacted-script-regular.woff2
│ └── stylesheet.css
├── index.html
├── manifest.json
└── problem-css-masonry.png
├── src
├── App.js
├── index.js
├── styles.css
└── styles.scss
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .sass-cache/
2 | *.css.map
3 | node_modules/
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Live Demo: [https://masonry-css-js.netlify.com/](https://masonry-css-js.netlify.com/)
2 |
3 | 
4 |
5 | CSS column-count for masonry-style layouts is dead easy (couple lines of CSS and very minimal markup to get it going).
6 |
7 | ## The Problem
8 | The problem (sometimes) is the way the content flows (see the diagram above). Typically, I want a left-to-right scan reading experience, i.e. cards of blog post summaries with the most recent posts to appear at the top of the view. I also don't want to use JS for the layout. Pure CSS... all the way.
9 |
10 | ## The Solution
11 | The only "help" that JS provides is re-ordering the array before rendering to the view so that we can use CSS column-count for the layout. Again, for example, this array could be a feed of recent news posts.
12 |
13 | Check the demo: [here](https://masonry-css-js.netlify.com/)
14 |
15 | Check out the code: [react component](https://github.com/jessekorzan/masonry-css-js/blob/master/src/App.js)
16 |
17 | Post on Medium: [Easy CSS Masonry Layout w/ Left-To-Right Content Flow](https://hackernoon.com/masonry-layout-technique-react-demo-of-100-css-control-of-the-view-e4190fa4296)
18 |
19 | Special thanks to my Klue teammate [@nickb](https://twitter.com/nickb) for figuring out the array re-order (and in a way even I could understand).
20 |
21 | ---
22 |
23 | This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
24 |
25 | Here's the guide [here](https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md).
26 |
27 |
--------------------------------------------------------------------------------
/build/asset-manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "main.css": "static/css/main.2e4c670b.css",
3 | "main.css.map": "static/css/main.2e4c670b.css.map",
4 | "main.js": "static/js/main.0a863532.js",
5 | "main.js.map": "static/js/main.0a863532.js.map"
6 | }
--------------------------------------------------------------------------------
/build/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/favicon.ico
--------------------------------------------------------------------------------
/build/fonts/redacted-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-regular.eot
--------------------------------------------------------------------------------
/build/fonts/redacted-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/build/fonts/redacted-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-regular.ttf
--------------------------------------------------------------------------------
/build/fonts/redacted-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-regular.woff
--------------------------------------------------------------------------------
/build/fonts/redacted-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-regular.woff2
--------------------------------------------------------------------------------
/build/fonts/redacted-script-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-bold.eot
--------------------------------------------------------------------------------
/build/fonts/redacted-script-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-bold.ttf
--------------------------------------------------------------------------------
/build/fonts/redacted-script-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-bold.woff
--------------------------------------------------------------------------------
/build/fonts/redacted-script-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-bold.woff2
--------------------------------------------------------------------------------
/build/fonts/redacted-script-light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-light.eot
--------------------------------------------------------------------------------
/build/fonts/redacted-script-light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-light.ttf
--------------------------------------------------------------------------------
/build/fonts/redacted-script-light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-light.woff
--------------------------------------------------------------------------------
/build/fonts/redacted-script-light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-light.woff2
--------------------------------------------------------------------------------
/build/fonts/redacted-script-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-regular.eot
--------------------------------------------------------------------------------
/build/fonts/redacted-script-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/build/fonts/redacted-script-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-regular.ttf
--------------------------------------------------------------------------------
/build/fonts/redacted-script-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-regular.woff
--------------------------------------------------------------------------------
/build/fonts/redacted-script-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/fonts/redacted-script-regular.woff2
--------------------------------------------------------------------------------
/build/fonts/stylesheet.css:
--------------------------------------------------------------------------------
1 | /* Generated by Font Squirrel (http://www.fontsquirrel.com) on March 2, 2013 */
2 |
3 |
4 |
5 | @font-face {
6 | font-family: 'redactedregular';
7 | src: url('redacted-regular.eot');
8 | src: url('redacted-regular.eot?#iefix') format('embedded-opentype'),
9 | url('redacted-regular.woff2') format('woff2'),
10 | url('redacted-regular.woff') format('woff'),
11 | url('redacted-regular.ttf') format('truetype'),
12 | url('redacted-regular.svg#redactedregular') format('svg');
13 | font-weight: normal;
14 | font-style: normal;
15 |
16 | }
17 |
18 |
19 |
20 |
21 | @font-face {
22 | font-family: 'redacted_scriptbold';
23 | src: url('redacted-script-bold.eot');
24 | src: url('redacted-script-bold.eot?#iefix') format('embedded-opentype'),
25 | url('redacted-script-bold.woff2') format('woff2'),
26 | url('redacted-script-bold.woff') format('woff'),
27 | url('redacted-script-bold.ttf') format('truetype'),
28 | url('redacted-script-bold.svg#redacted_scriptbold') format('svg');
29 | font-weight: normal;
30 | font-style: normal;
31 |
32 | }
33 |
34 |
35 |
36 |
37 | @font-face {
38 | font-family: 'redacted_scriptlight';
39 | src: url('redacted-script-light.eot');
40 | src: url('redacted-script-light.eot?#iefix') format('embedded-opentype'),
41 | url('redacted-script-light.woff2') format('woff2'),
42 | url('redacted-script-light.woff') format('woff'),
43 | url('redacted-script-light.ttf') format('truetype'),
44 | url('redacted-script-light.svg#redacted_scriptlight') format('svg');
45 | font-weight: normal;
46 | font-style: normal;
47 |
48 | }
49 |
50 |
51 |
52 |
53 | @font-face {
54 | font-family: 'redacted_scriptregular';
55 | src: url('redacted-script-regular.eot');
56 | src: url('redacted-script-regular.eot?#iefix') format('embedded-opentype'),
57 | url('redacted-script-regular.woff2') format('woff2'),
58 | url('redacted-script-regular.woff') format('woff'),
59 | url('redacted-script-regular.ttf') format('truetype'),
60 | url('redacted-script-regular.svg#redacted_scriptregular') format('svg');
61 | font-weight: normal;
62 | font-style: normal;
63 |
64 | }
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
CSS Masonry Layout (left-to-right content flow)
--------------------------------------------------------------------------------
/build/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/build/problem-css-masonry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/build/problem-css-masonry.png
--------------------------------------------------------------------------------
/build/service-worker.js:
--------------------------------------------------------------------------------
1 | "use strict";var precacheConfig=[["/index.html","577fded0ce4de960e830a492c9f7239f"],["/static/css/main.2e4c670b.css","1c61b50e9587f3291be4a0b851deeeb2"],["/static/js/main.0a863532.js","f7a86151e048e9ce8243d6e83e734141"]],cacheName="sw-precache-v3-sw-precache-webpack-plugin-"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},cleanResponse=function(t){return t.redirected?("body"in t?Promise.resolve(t.body):t.blob()).then(function(e){return new Response(e,{headers:t.headers,status:t.status,statusText:t.statusText})}):Promise.resolve(t)},createCacheKey=function(e,t,n,r){var a=new URL(e);return r&&a.pathname.match(r)||(a.search+=(a.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),a.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,n){var t=new URL(e);return t.hash="",t.search=t.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(t){return n.every(function(e){return!e.test(t[0])})}).map(function(e){return e.join("=")}).join("&"),t.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],r=new URL(t,self.location),a=createCacheKey(r,hashParamName,n,/\.\w{8}\./);return[r.toString(),a]}));function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(r){return setOfCachedUrls(r).then(function(n){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(t){if(!n.has(t)){var e=new Request(t,{credentials:"same-origin"});return fetch(e).then(function(e){if(!e.ok)throw new Error("Request for "+t+" returned a response with status "+e.status);return cleanResponse(e).then(function(e){return r.put(t,e)})})}}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var n=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(t){return t.keys().then(function(e){return Promise.all(e.map(function(e){if(!n.has(e.url))return t.delete(e)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(t){if("GET"===t.request.method){var e,n=stripIgnoredUrlParameters(t.request.url,ignoreUrlParametersMatching),r="index.html";(e=urlsToCacheKeys.has(n))||(n=addDirectoryIndex(n,r),e=urlsToCacheKeys.has(n));var a="/index.html";!e&&"navigate"===t.request.mode&&isPathWhitelisted(["^(?!\\/__).*"],t.request.url)&&(n=new URL(a,self.location).toString(),e=urlsToCacheKeys.has(n)),e&&t.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n)).then(function(e){if(e)return e;throw Error("The cached response that was expected is missing.")})}).catch(function(e){return console.warn('Couldn\'t serve response for "%s" from cache: %O',t.request.url,e),fetch(t.request)}))}});
--------------------------------------------------------------------------------
/build/static/css/main.2e4c670b.css:
--------------------------------------------------------------------------------
1 | @import url(https://fonts.googleapis.com/css?family=Heebo:400,600,700);/*! normalize.css v8.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}html{-webkit-box-sizing:border-box;box-sizing:border-box}*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}body{background:#f5f3f3;color:#2b2929;font-family:Heebo,sans-serif;font-size:13px;line-height:24px;font-weight:400;margin:0;padding:0}h1,h2,h3,h4{margin:0 0 14.66667px}a{color:#0090ff;text-decoration:none}nav{height:44px;text-align:center;padding:4px}nav,nav a{background:#2b2929}nav a{border:1px solid #004880;color:#0090ff;padding:0 8.8px;border-left:none;height:36px;text-transform:uppercase;font-size:12px;line-height:36px;text-decoration:none;cursor:pointer;display:inline-block}nav a:focus{outline:none}nav a:first-child{border-left:1px solid #004880}nav a:active,nav a:target{background:#0090ff;color:#f5f3f3}.layout--wrapper{height:calc(100vh - 44px);overflow-y:scroll}.layout{padding:14.66667px}.layout.flex{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:distribute;justify-content:space-around;-ms-flex-align:stretch;align-items:stretch}.layout.flex .card{width:20%}.layout.masonry{-webkit-column-count:5;column-count:5;-webkit-column-gap:6.66667px;column-gap:6.66667px}.layout.masonry .card{-webkit-column-break-inside:avoid;break-inside:avoid}.layout.masonry .card:nth-child(6n+1){clear:left}.layout.single-column{width:440px;margin:0 auto}.layout.two-column{max-width:800px;margin:0 auto;-webkit-column-count:2;column-count:2;-webkit-column-gap:6.66667px;column-gap:6.66667px}.layout.two-column .card{-webkit-column-break-inside:avoid;break-inside:avoid}.info{text-align:center;padding:14.66667px}.info *{margin:8px 0 0}.info span{background:#fff;border:1px solid #f5f3f3;margin-right:2px;width:30px;height:30px;line-height:30px;font-weight:600;font-size:14px;text-align:center;display:inline-block}.card{position:relative;border:4px solid #f5f3f3;background:#fff;min-height:288px;width:100%;margin-bottom:6.66667px;color:#aca7a7}.card>div{padding:22px}.card .media{position:relative;min-height:200px;height:15vh;overflow:hidden;padding:0;background:#d2c9c9}.card .media img{-webkit-filter:grayscale(100%);filter:grayscale(100%);width:100%}.card h2,.card h3,.card h4,.card p{font-family:redacted_scriptbold}.card.active{border-color:#0090ff;color:#0090ff}
2 | /*# sourceMappingURL=main.2e4c670b.css.map*/
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "feed-layouts",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "node-sass-chokidar": "0.0.3",
7 | "normalize.css": "^8.0.0",
8 | "npm-run-all": "^4.1.1",
9 | "react": "^16.3.1",
10 | "react-dom": "^16.3.1",
11 | "react-scripts": "1.1.4"
12 | },
13 | "scripts": {
14 | "build-css": "node-sass-chokidar src/ -o src/",
15 | "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
16 | "start-js": "react-scripts start",
17 | "start": "npm-run-all -p watch-css start-js",
18 | "build": "npm run build-css && react-scripts build",
19 | "test": "react-scripts test --env=jsdom",
20 | "eject": "react-scripts eject"
21 | }
22 | }
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/favicon.ico
--------------------------------------------------------------------------------
/public/fonts/redacted-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-regular.eot
--------------------------------------------------------------------------------
/public/fonts/redacted-regular.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/public/fonts/redacted-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-regular.ttf
--------------------------------------------------------------------------------
/public/fonts/redacted-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-regular.woff
--------------------------------------------------------------------------------
/public/fonts/redacted-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-regular.woff2
--------------------------------------------------------------------------------
/public/fonts/redacted-script-bold.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-bold.eot
--------------------------------------------------------------------------------
/public/fonts/redacted-script-bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-bold.ttf
--------------------------------------------------------------------------------
/public/fonts/redacted-script-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-bold.woff
--------------------------------------------------------------------------------
/public/fonts/redacted-script-bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-bold.woff2
--------------------------------------------------------------------------------
/public/fonts/redacted-script-light.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-light.eot
--------------------------------------------------------------------------------
/public/fonts/redacted-script-light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-light.ttf
--------------------------------------------------------------------------------
/public/fonts/redacted-script-light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-light.woff
--------------------------------------------------------------------------------
/public/fonts/redacted-script-light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-light.woff2
--------------------------------------------------------------------------------
/public/fonts/redacted-script-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-regular.eot
--------------------------------------------------------------------------------
/public/fonts/redacted-script-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-regular.ttf
--------------------------------------------------------------------------------
/public/fonts/redacted-script-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-regular.woff
--------------------------------------------------------------------------------
/public/fonts/redacted-script-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/fonts/redacted-script-regular.woff2
--------------------------------------------------------------------------------
/public/fonts/stylesheet.css:
--------------------------------------------------------------------------------
1 | /* Generated by Font Squirrel (http://www.fontsquirrel.com) on March 2, 2013 */
2 |
3 |
4 |
5 | @font-face {
6 | font-family: 'redactedregular';
7 | src: url('redacted-regular.eot');
8 | src: url('redacted-regular.eot?#iefix') format('embedded-opentype'),
9 | url('redacted-regular.woff2') format('woff2'),
10 | url('redacted-regular.woff') format('woff'),
11 | url('redacted-regular.ttf') format('truetype'),
12 | url('redacted-regular.svg#redactedregular') format('svg');
13 | font-weight: normal;
14 | font-style: normal;
15 |
16 | }
17 |
18 |
19 |
20 |
21 | @font-face {
22 | font-family: 'redacted_scriptbold';
23 | src: url('redacted-script-bold.eot');
24 | src: url('redacted-script-bold.eot?#iefix') format('embedded-opentype'),
25 | url('redacted-script-bold.woff2') format('woff2'),
26 | url('redacted-script-bold.woff') format('woff'),
27 | url('redacted-script-bold.ttf') format('truetype'),
28 | url('redacted-script-bold.svg#redacted_scriptbold') format('svg');
29 | font-weight: normal;
30 | font-style: normal;
31 |
32 | }
33 |
34 |
35 |
36 |
37 | @font-face {
38 | font-family: 'redacted_scriptlight';
39 | src: url('redacted-script-light.eot');
40 | src: url('redacted-script-light.eot?#iefix') format('embedded-opentype'),
41 | url('redacted-script-light.woff2') format('woff2'),
42 | url('redacted-script-light.woff') format('woff'),
43 | url('redacted-script-light.ttf') format('truetype'),
44 | url('redacted-script-light.svg#redacted_scriptlight') format('svg');
45 | font-weight: normal;
46 | font-style: normal;
47 |
48 | }
49 |
50 |
51 |
52 |
53 | @font-face {
54 | font-family: 'redacted_scriptregular';
55 | src: url('redacted-script-regular.eot');
56 | src: url('redacted-script-regular.eot?#iefix') format('embedded-opentype'),
57 | url('redacted-script-regular.woff2') format('woff2'),
58 | url('redacted-script-regular.woff') format('woff'),
59 | url('redacted-script-regular.ttf') format('truetype'),
60 | url('redacted-script-regular.svg#redacted_scriptregular') format('svg');
61 | font-weight: normal;
62 | font-style: normal;
63 |
64 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
22 | CSS Masonry Layout (left-to-right content flow)
23 |
24 |
25 |
26 |
29 |
30 |
40 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/public/problem-css-masonry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jessekorzan/masonry-css-js/ec74593b544fcae122a24b6d707b81b43ae4bd20/public/problem-css-masonry.png
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import 'normalize.css';
3 | import './styles.css';
4 |
5 | // Jesse Korzan
6 | // copyright 2018 Klue Labs
7 | // CSS column-count masonry w/ left-right reflow
8 | // special thx to NickB
9 | //
10 | // kick ass out there, ppl 1:1
11 |
12 | const Card = (props) =>
13 | props.handleClickCard(props.card)}>
14 |
15 |
16 |
{ props.card.id }
17 |
{ props.card.title }
18 |
{ props.card.title }{ props.card.body }
19 |
20 |
21 |
22 | const Layout = (props) =>
23 | // Masonry layout of cards
24 | // column-count : X
25 |
26 | {props.cards.map( (card, index) =>
27 |
28 | )}
29 |
30 |
31 | class App extends Component {
32 | constructor() {
33 | super();
34 | this.state = {
35 | layout: "masonry",
36 | columns: 5,
37 | maxCards: 20
38 | };
39 | }
40 | componentDidMount() {
41 | this.fetchEr();
42 |
43 | /*
44 | // cheap responsive approach -- if you want
45 | window.addEventListener("resize", () => {
46 | let winWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
47 | if (winWidth <= 900) {
48 | this.reorder(this.state.cardsOG, 2);
49 | } else {
50 | this.reorder(this.state.cardsOG, 5);
51 | }
52 | })
53 | */
54 | }
55 | fetchEr = () => {
56 | fetch(`https://jsonplaceholder.typicode.com/posts`)
57 | .then(response => response.json())
58 | .then(result => {
59 | this.reorder(result.slice(0,this.state.maxCards), this.state.columns);
60 | this.setState({ cardsOG: result.slice(0,this.state.maxCards) });
61 | })
62 | .catch(e => e);
63 | }
64 | reorder = (arr, columns) => {
65 | // READ HERE
66 | // this is the magic
67 | // re-order the array so the "cards" read left-right
68 | // cols === CSS column-count value
69 |
70 | const cols = columns;
71 | const out = [];
72 | let col = 0;
73 | while(col < cols) {
74 | for(let i = 0; i < arr.length; i += cols) {
75 | let _val = arr[i + col];
76 | if (_val !== undefined)
77 | out.push(_val);
78 | }
79 | col++;
80 | }
81 | this.setState({ cards: out, columns: columns });
82 |
83 | // yes, I know Nick... you had another slicker ES6-y implementation
84 | // but this one I could understand :)
85 | }
86 | handleButtonClick = (layout, columns) => {
87 | this.setState({
88 | layout: layout,
89 | columns: columns
90 | });
91 | this.reorder(this.state.cardsOG, columns);
92 |
93 | }
94 | handleClickCard = (card) => {
95 | this.setState({
96 | cardActive: (this.state.cardActive !== card) ? card : false
97 | })
98 | }
99 | render() {
100 | let CARDS = this.state.cards;
101 | return (
102 |
120 | );
121 | }
122 | }
123 |
124 | export default App;
125 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | @import url("https://fonts.googleapis.com/css?family=Heebo:400,600,700");
2 | html {
3 | box-sizing: border-box; }
4 |
5 | *, *:before, *:after {
6 | box-sizing: inherit; }
7 |
8 | body {
9 | background: #f5f3f3;
10 | color: #2b2929;
11 | font-family: "Heebo", sans-serif;
12 | font-size: 13px;
13 | line-height: 24px;
14 | font-weight: 400;
15 | margin: 0;
16 | padding: 0; }
17 |
18 | h1, h2, h3, h4 {
19 | margin: 0 0 14.66667px; }
20 |
21 | a {
22 | color: #0090ff;
23 | text-decoration: none; }
24 |
25 | nav {
26 | background: #2b2929;
27 | height: 44px;
28 | text-align: center;
29 | padding: 4px; }
30 | nav a {
31 | border: 1px solid #004880;
32 | background: #2b2929;
33 | color: #0090ff;
34 | padding: 0 8.8px;
35 | border-left: none;
36 | height: 36px;
37 | text-transform: uppercase;
38 | font-size: 12px;
39 | line-height: 36px;
40 | text-decoration: none;
41 | cursor: pointer;
42 | display: inline-block; }
43 | nav a:focus {
44 | outline: none; }
45 | nav a:first-child {
46 | border-left: 1px solid #004880; }
47 | nav a:active, nav a:target {
48 | background: #0090ff;
49 | color: #f5f3f3; }
50 |
51 | .layout--wrapper {
52 | height: calc(100vh - 44px);
53 | overflow-y: scroll; }
54 |
55 | .layout {
56 | padding: 14.66667px; }
57 | .layout.flex {
58 | display: flex;
59 | flex-wrap: wrap;
60 | justify-content: center;
61 | align-items: stretch; }
62 | .layout.flex .card {
63 | width: 16.666667%;
64 | height: 420px;
65 | margin-bottom: 0; }
66 | .layout.flex .card p {
67 | width: 80%;
68 | white-space: nowrap;
69 | overflow: hidden;
70 | text-overflow: ellipsis; }
71 | @media screen and (max-width: 1419px) {
72 | .layout.flex .card {
73 | width: 20%; } }
74 | @media screen and (max-width: 1023px) {
75 | .layout.flex .card {
76 | width: 25%; } }
77 | @media screen and (max-width: 727px) {
78 | .layout.flex .card {
79 | width: 33.33334%; } }
80 | @media screen and (max-width: 600px) {
81 | .layout.flex .card {
82 | width: 50%; } }
83 | .layout.masonry {
84 | column-count: 5;
85 | column-gap: 0.8px; }
86 | .layout.masonry .card {
87 | break-inside: avoid;
88 | page-break-inside: avoid; }
89 | .layout.masonry .card:nth-child(6n+1) {
90 | clear: left; }
91 | .layout.single-column {
92 | max-width: 440px;
93 | margin: 0 auto; }
94 | .layout.two-column {
95 | max-width: 800px;
96 | margin: 0 auto;
97 | column-count: 2;
98 | column-gap: 0.8px; }
99 | .layout.two-column .card {
100 | break-inside: avoid;
101 | page-break-inside: avoid; }
102 |
103 | .info {
104 | text-align: center;
105 | padding: 11px; }
106 | .info > * {
107 | margin: 8px 0 0; }
108 | .info h2 {
109 | line-height: 32px; }
110 | .info span {
111 | background: #fff;
112 | border: #f5f3f3 solid 1px;
113 | margin-right: 1px;
114 | width: 30px;
115 | height: 30px;
116 | line-height: 30px;
117 | font-weight: 600;
118 | font-size: 14px;
119 | text-align: center;
120 | display: inline-block; }
121 |
122 | .card {
123 | position: relative;
124 | border: 4px solid #f5f3f3;
125 | background: #fff;
126 | min-height: 288px;
127 | width: 100%;
128 | margin-bottom: 0.8px;
129 | color: #aca7a7;
130 | break-inside: avoid;
131 | page-break-inside: avoid; }
132 | .card > div {
133 | padding: 22px; }
134 | .card .media {
135 | position: relative;
136 | min-height: 200px;
137 | height: 15vh;
138 | overflow: hidden;
139 | padding: 0;
140 | background: rgba(51, 102, 153, 0.15);
141 | border: 6px solid #fff; }
142 | .card .media img {
143 | filter: grayscale(100%);
144 | width: 100%; }
145 | .card h2, .card h3, .card h4, .card p {
146 | font-family: "redacted_scriptbold"; }
147 | .card.active {
148 | border-color: #0090ff;
149 | color: #0090ff; }
150 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css?family=Heebo:400,600,700');
2 | $font : "Heebo";
3 |
4 | $black : #2b2929;
5 | $blue : #0090ff;
6 | $white: #fff;
7 | $grey: #f5f3f3;
8 | $red: #c80722;
9 |
10 | $spacer: 44px;
11 |
12 | html {
13 | box-sizing: border-box;
14 | }
15 | *, *:before, *:after {
16 | box-sizing: inherit;
17 | }
18 |
19 | body {
20 | background: $grey;
21 | color: $black;
22 | font-family: $font, sans-serif;
23 | font-size: 13px;
24 | line-height: 24px;
25 | font-weight: 400;
26 | margin: 0;
27 | padding: 0;
28 | }
29 | h1, h2, h3, h4 {
30 | margin: 0 0 $spacer/3;
31 | }
32 |
33 | a {
34 | color: $blue;
35 | text-decoration: none;
36 | }
37 |
38 |
39 | nav {
40 | background: $black;
41 | height: $spacer;
42 | text-align: center;
43 | padding: 4px;
44 | a {
45 | border: 1px solid darken($blue, 25%);
46 | background: $black;
47 | color: $blue;
48 | padding: 0 $spacer/5;
49 | border-left: none;
50 | height: 36px;
51 | text-transform: uppercase;
52 | font-size: 12px;
53 | line-height: 36px;
54 | text-decoration: none;
55 | cursor: pointer;
56 | display: inline-block;
57 | &:focus {
58 | outline: none;
59 | }
60 | &:first-child {
61 | border-left: 1px solid darken($blue, 25%);
62 | }
63 | &:active, &:target {
64 | background: $blue;
65 | color: $grey;
66 | }
67 | }
68 | }
69 |
70 |
71 |
72 | .layout--wrapper {
73 | height: calc(100vh - 44px);
74 | overflow-y: scroll;
75 | }
76 | .layout {
77 | padding: $spacer/3;
78 | &.flex {
79 | display: flex;
80 | flex-wrap: wrap;
81 | justify-content: center;
82 | align-items: stretch;
83 | .card {
84 | width: 16.666667%;
85 | height: 420px;
86 | margin-bottom: 0;
87 | p {
88 | width: 80%;
89 | white-space: nowrap;
90 | overflow: hidden;
91 | text-overflow: ellipsis;
92 | }
93 | @media screen and (max-width: 1419px) {
94 | width: 20%;
95 | }
96 | @media screen and (max-width: 1023px) {
97 | width: 25%;
98 | }
99 | @media screen and (max-width: 727px) {
100 | width: 33.33334%;
101 | }
102 | @media screen and (max-width: 600px) {
103 | width: 50%;
104 | }
105 | }
106 | }
107 | &.masonry {
108 | column-count: 5;
109 | column-gap: $spacer/5 - 8px;
110 | .card {
111 | break-inside: avoid;
112 | page-break-inside: avoid;
113 | }
114 | .card:nth-child(6n+1){
115 | clear: left;
116 | }
117 | }
118 | &.single-column {
119 | max-width: 440px;
120 | margin: 0 auto;
121 | }
122 | &.two-column {
123 | max-width: 800px;
124 | margin: 0 auto;
125 | column-count: 2;
126 | column-gap: $spacer/5 - 8px;
127 | .card {
128 | break-inside: avoid;
129 | page-break-inside: avoid;
130 | }
131 | }
132 | }
133 | .info {
134 | text-align: center;
135 | padding: $spacer/4;
136 | > * {
137 | margin: 8px 0 0;
138 | }
139 | h2 {
140 | line-height: 32px;
141 | }
142 | span {
143 | background: $white;
144 | border: $grey solid 1px;
145 | margin-right: 1px;
146 | width:30px;
147 | height: 30px;
148 | line-height: 30px;
149 | font-weight: 600;
150 | font-size: 14px;
151 | text-align: center;
152 | display: inline-block;
153 | //font-family: monospace;
154 | }
155 | }
156 | .card {
157 | position: relative;
158 | border: 4px solid $grey;
159 | background: $white;
160 | min-height: 288px;
161 | width: 100%;
162 | margin-bottom: $spacer/5 - 8px;
163 | color: lighten($black, 50%);
164 | break-inside: avoid;
165 | page-break-inside: avoid;
166 | > div {
167 | padding: $spacer/2;
168 | }
169 | .media {
170 | position: relative;
171 | min-height: 200px;
172 | height: 15vh;
173 | overflow: hidden;
174 | padding: 0;
175 | background: rgba(#336699, 0.15);
176 | border: 6px solid $white;
177 | img {
178 | filter: grayscale(100%);
179 | width: 100%;
180 | }
181 | }
182 | h2, h3, h4, p {
183 | font-family: "redacted_scriptbold";
184 | }
185 | &.active {
186 | border-color: $blue;
187 | color: $blue;
188 | }
189 | }
190 |
--------------------------------------------------------------------------------