diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..bc40ce9
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+root = true
+
+# Defaults
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+# Markdown
+[*.md]
+indent_size = 4
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3fd963f
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+readme.md
+docs/index.html
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..ef3b812
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,17 @@
+{
+ "extends": [
+ "eslint-config-airbnb-base"
+ ],
+ "env": {
+ "browser": true,
+ "es6": true
+ },
+ "rules": {
+ "class-methods-use-this": "off",
+ "no-param-reassign": "off",
+ "no-return-assign": "off",
+ "no-underscore-dangle": "off",
+ "prefer-destructuring": "off",
+ "prefer-template": "off"
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d1558d2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+# Build Files
+*.map
diff --git a/.stylelintrc b/.stylelintrc
new file mode 100644
index 0000000..9bcac18
--- /dev/null
+++ b/.stylelintrc
@@ -0,0 +1,15 @@
+{
+ "plugins": [
+ "stylelint-order"
+ ],
+ "extends": [
+ "stylelint-config-standard",
+ "stylelint-config-property-sort-order-smacss",
+ ],
+ "rules": {
+ "comment-empty-line-before": null,
+ "max-empty-lines": 3,
+ "no-descending-specificity": null,
+ "no-duplicate-selectors": null
+ }
+}
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000..cd32018
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,17 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [1.1.0] - 2020-08-10
+
+### Changed
+
+- Open source the project!
+
+[Unreleased]: https://github.com/tannerhodges/match-height/compare/v1.1.0...HEAD
+[1.1.0]: https://github.com/tannerhodges/match-height/releases/tag/v1.1.0
diff --git a/docs/demo.css b/docs/demo.css
new file mode 100644
index 0000000..53b5f51
--- /dev/null
+++ b/docs/demo.css
@@ -0,0 +1,200 @@
+/* ------------------------------ */
+/* Reset */
+/* ------------------------------ */
+
+html {
+ box-sizing: border-box;
+ font-family: sans-serif;
+ line-height: 1.5;
+ tab-size: 4;
+ scroll-behavior: smooth;
+}
+
+*,
+::after,
+::before {
+ box-sizing: inherit;
+}
+
+body {
+ margin: 1rem auto 0;
+}
+
+body::after {
+ content: '🦕';
+ display: block;
+ margin-top: 10rem;
+ margin-bottom: 1rem;
+ font-size: 3rem;
+ text-align: center;
+}
+
+main {
+ display: block; /* Fix IE rendering main as inline */
+ max-width: 40rem;
+ margin: 0 auto;
+ padding-right: 1rem;
+ padding-left: 1rem;
+}
+
+pre {
+ padding: 1rem;
+ overflow: auto;
+ border: 1px solid #ccc;
+ color: #888;
+ -webkit-overflow-scroll: touch;
+}
+
+a {
+ color: blue;
+}
+
+a:focus,
+a:hover {
+ color: lightblue;
+}
+
+a:active {
+ color: blue;
+}
+
+/* Font Styles & Sizes */
+h1 {
+ margin-bottom: 0;
+ font-family: 'Bowlby One SC', 'Arial Black', sans-serif;
+ font-size: 8vw;
+ text-align: center;
+}
+
+h2 {
+ font-family: 'Bowlby One SC', 'Arial Black', sans-serif;
+ text-align: center;
+}
+
+main > p,
+main > ul {
+ font-family: 'Indie Flower', serif;
+ font-size: 1.333rem;
+}
+
+li {
+ margin-bottom: 1em;
+}
+
+/* Desktop Font Sizes */
+@media (min-width: 768px) {
+ h1 {
+ font-size: 4rem;
+ }
+
+ h2 {
+ font-size: 2rem;
+ }
+
+ main > p,
+ main > ul {
+ font-size: 2rem;
+ }
+
+ pre {
+ font-size: 1.333rem;
+ }
+}
+
+/* Vertical Rhythm */
+pre {
+ margin-bottom: 3rem;
+}
+
+h2 {
+ margin-top: 4rem;
+}
+
+
+
+/* ------------------------------ */
+/* Fun */
+/* ------------------------------ */
+
+.h1 {
+ position: relative;
+ width: max-content;
+ margin-right: auto;
+ margin-left: auto;
+}
+
+.h1__dino {
+ position: absolute;
+ right: 100%;
+ margin-right: 1rem;
+}
+
+
+
+/* ------------------------------ */
+/* Demo */
+/* ------------------------------ */
+
+.example {
+ outline: 1px dashed black;
+}
+
+.example__item {
+ flex: 1 1 33%;
+}
+
+.example__heading {
+ margin: 0;
+ padding: 2rem 1rem;
+ background: #ddd;
+ text-align: center;
+}
+
+.example__image {
+ display: block;
+ width: 100%;
+ height: 200px;
+ object-fit: cover;
+}
+
+/* Placeholder Colors */
+.example__image:nth-child(n + 1) {
+ background: #eee;
+}
+
+.example__image:nth-child(n + 2) {
+ background: #ddd;
+}
+
+.example__image:nth-child(n + 3) {
+ background: #ccc;
+}
+
+.example__text {
+ margin: 0;
+ padding: 2rem 1rem;
+}
+
+
+
+/* ------------------------------ */
+/* Example 1 */
+/* ------------------------------ */
+
+.example--1 {
+ display: flex;
+ align-items: flex-start;
+}
+
+
+
+/* ------------------------------ */
+/* Example 2 */
+/* ------------------------------ */
+
+@media (min-width: 560px) {
+ .example--2 {
+ display: flex;
+ align-items: flex-start;
+ }
+}
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..b5a6ee2
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,209 @@
+
+
+
+
+ 🦖 Match Height
+ So you want to make your elements the same height, huh?
+ CSS not cutting it?
+ Yep, we know.
+
+ Basic Example
+ Flexbox & CSS Grid are amazing tools, but until we get CSS Subgrid you still need JavaScript to match elements across containers.
+ Match Height makes this as easy as adding a data-match-height attribute.
+<h3 data-match-height="heading">My Example Heading</h3>
+
+
+
Person 1
+
+
Stuff about person 1.
+
+
+
Person 2
+
+
So much stuff about person 2. You wouldn't believe how interesting they are. We could just talk about them all day.
+
+
+
Person With a Long Name
+
+
Stuff about person with a long name.
+
+
+
+ Responsive Example
+ But how do I turn it off on mobile?
+ Simple! Add data-match-height-enable to your container element.
+<div data-match-height-enable="(min-width: 560px)">
+ ...
+</div>
+
+
+
Person 1
+
+
Stuff about person 1.
+
+
+
Person 2
+
+
So much stuff about person 2. You wouldn't believe how interesting they are. We could just talk about them all day.
+
+
+
Person With a Long Name
+
+
Stuff about person with a long name.
+
+
+
+ Grouping Elements
+ What if I have different groups of elements with the same name? How can I match them separately?
+ You've got a couple options.
+ 1. Use the data-match-height-group attribute to wrap elements in a more specific group.
+<div data-match-height-group="group-1">
+ <div><h3 data-match-height="heading"></h3></div>
+ <div><h3 data-match-height="heading"></h3></div>
+ <div><h3 data-match-height="heading"></h3></div>
+</div>
+<div data-match-height-group="group-2">
+ <div><h3 data-match-height="heading"></h3></div>
+ <div><h3 data-match-height="heading"></h3></div>
+ <div><h3 data-match-height="heading"></h3></div>
+</div>
+ 2. Or, if you need to keep your elements in the same container, add prefixes to your group names.
+<div>
+ <div><h3 data-match-height="group-1-heading"></h3></div>
+ <div><h3 data-match-height="group-1-heading"></h3></div>
+ <div><h3 data-match-height="group-1-heading"></h3></div>
+ <div><h3 data-match-height="group-2-heading"></h3></div>
+ <div><h3 data-match-height="group-2-heading"></h3></div>
+ <div><h3 data-match-height="group-2-heading"></h3></div>
+</div>
+
+ Triggering Updates
+ If you ever need to force-update elements, call MatchHeight.update().
+ To help save the planet, you can also limit your update to a specific group of elements.
+MatchHeight.update();
+
+// or
+
+MatchHeight.update('.your-elements');
+ Need to start over? Call MatchHeight.reset().
+MatchHeight.reset();
+
+ Declarative & Imperative
+ Big words!
+ While we recommend using HTML attributes for most cases, sometimes you do need control to programmatically match elements.
+ For that, we offer MatchHeight.add().
+MatchHeight.add('.your-elements');
+
+// or
+
+MatchHeight.add('.your-elements', 'some-group');
+ Elements are added to a new, unique group by default, but you can also specify a group to add them to.
+
+ jQuery-Friendly
+ We don't require jQuery, but we do love all you jQuery power users out there!
+ As long as you load jQuery first, we'll add a handy .matchHeight() function just for you.
+<script src="jquery.js"></script>
+<script src="match-height.js"></script>
+<script>
+ $('.jquery-elements').matchHeight();
+</script>
+
+ SPA-Friendly
+ What's that? You're using the latest and greatest JS frameworks?
+ Excellent!
+ To integrate Match Height, just call MatchHeight.reset() when your app mounts...
+const app = new Vue({
+ el: '#app',
+ mounted() {
+ MatchHeight.reset();
+ },
+});
+ Or use MatchHeight.add() when your components mount...
+Vue.component('person', {
+ props: ['person'],
+ template: `
+ <div>
+ <h3 v-text="person.name" ref="heading"></h3>
+ <img :src="person.image" alt="">
+ <p v-text="person.description"></p>
+ </div>
+ `,
+ mounted() {
+ this.$nextTick(() => MatchHeight.add(this.$refs.heading, 'person-heading'));
+ },
+ beforeDestroy() {
+ MatchHeight.remove(this.$refs.heading, 'person-heading');
+ },
+});
+ Either way, the power is yours!
+
+ Debugging
+ If your powers grow wildly out of control, use MatchHeight.debug() to help get a grip on things.
+ Just specify a group or element to get all the details...
+// Running any of these...
+
+MatchHeight.debug('group-id');
+MatchHeight.debug('.your-class');
+MatchHeight.debug(element);
+MatchHeight.debug(elements);
+
+// will console.log()...
+
+{
+ isEnabled: true
+ control: div.example
+ enable: "(min-width: 560px)"
+ disable: null
+ groupID: "example-heading"
+ group: (3) [h3.example__heading, h3.example__heading, h3.example__heading]
+}
+ And with that, we bid you adieu!
+ Go forth and match responsibly.
+
+ P.S. CSS Subgrid
+ Keep an eye on CSS Subgrid. When that's supported everywhere, you won't need this plugin anymore!
+@media (min-width: 560px) {
+ .example {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ .example__item {
+ display: grid;
+ grid-template-rows: subgrid;
+ grid-row: auto / span 3;
+ }
+}
+
+
+
+
diff --git a/docs/match-height.js b/docs/match-height.js
new file mode 100644
index 0000000..76a1135
--- /dev/null
+++ b/docs/match-height.js
@@ -0,0 +1,2 @@
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.MatchHeight=e():t.MatchHeight=e()}(window,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){"use strict";function n(t){for(var e="",r=0;r