summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajab Natshah2018-02-25 12:12:37 (GMT)
committerRajab Natshah2018-02-25 12:12:37 (GMT)
commit8d7155675d6ac998a66daa3ea0c40a414161d245 (patch)
treea009a1cc8126cbedb837d9ed13ea207086f60c7a
parent69eea097e33397827f508bf4e8376a2b90149c97 (diff)
Issue #2947698: Added [Card] Vartheme bootstrap card, as a custom component library to help style [VMI] vertical media teasers, and text teasers
-rw-r--r--VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.libraries.yml6
-rw-r--r--VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.starterkit.yml1
-rw-r--r--VARTHEME_SUBTHEME/css/component/card.component.css194
-rw-r--r--VARTHEME_SUBTHEME/less/component/card.component.less280
-rw-r--r--VARTHEME_SUBTHEME/less/variables.less27
-rw-r--r--css/component/card.component.css194
-rw-r--r--css/theme/betterlogin.theme.css3
-rw-r--r--less/component/card.component.less280
-rw-r--r--less/variables.less27
-rwxr-xr-xvartheme.info.yml1
-rw-r--r--vartheme.libraries.yml6
11 files changed, 1011 insertions, 8 deletions
diff --git a/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.libraries.yml b/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.libraries.yml
index 84dcc98..0fec226 100644
--- a/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.libraries.yml
+++ b/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.libraries.yml
@@ -118,6 +118,12 @@ bootstrap-scripts:
# component:
# css/component/bs-callouts.component.css: {}
+# Vartheme bootstrap card component.
+#card:
+# css:
+# component:
+# css/component/card.component.css: {}
+
# Vartheme Outside in component library.
#outside-in:
# css:
diff --git a/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.starterkit.yml b/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.starterkit.yml
index 085eedd..35e5037 100644
--- a/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.starterkit.yml
+++ b/VARTHEME_SUBTHEME/VARTHEME_SUBTHEME.starterkit.yml
@@ -67,6 +67,7 @@ libraries-override:
# overriden library.
# ------------------------------------------------------------------------------
# vartheme/bs-callouts: VARTHEME_SUBTHEME/bs-callouts
+# vartheme/card: VARTHEME_SUBTHEME/card
# vartheme/outside-in: VARTHEME_SUBTHEME/outside-in
# vartheme/edge2edge: VARTHEME_SUBTHEME/edge2edge
# vartheme/equal-height: VARTHEME_SUBTHEME/equal-height
diff --git a/VARTHEME_SUBTHEME/css/component/card.component.css b/VARTHEME_SUBTHEME/css/component/card.component.css
new file mode 100644
index 0000000..f0f7c15
--- /dev/null
+++ b/VARTHEME_SUBTHEME/css/component/card.component.css
@@ -0,0 +1,194 @@
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 4px;
+}
+.card > hr {
+ margin-right: 0;
+ margin-left: 0;
+}
+.card > .list-group:first-child .list-group-item:first-child {
+ border-radius: 4px;
+}
+.card > .list-group:last-child .list-group-item:last-child {
+ border-radius: 4px;
+}
+.card-body {
+ flex: 1 1 auto;
+ padding: 1.25rem;
+}
+.card-title {
+ margin-bottom: 0.75rem;
+}
+.card-subtitle {
+ margin-top: -0.375rem;
+ margin-bottom: 0;
+}
+.card-text:last-child {
+ margin-bottom: 0;
+}
+.card-link::hover {
+ text-decoration: none;
+}
+.card-link + .card-link {
+ margin-left: 1.25rem;
+}
+.card-header {
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 0;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-header:first-child {
+ border-radius: calc(3px) calc(3px) 0 0;
+}
+.card-header + .list-group .list-group-item:first-child {
+ border-top: 0;
+}
+.card-footer {
+ padding: 0.75rem 1.25rem;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-footer:last-child {
+ border-radius: 0 0 calc(3px) calc(3px);
+}
+.card-header-tabs {
+ margin-right: -0.625rem;
+ margin-bottom: -0.75rem;
+ margin-left: -0.625rem;
+ border-bottom: 0;
+}
+.card-header-pills {
+ margin-right: -0.625rem;
+ margin-left: -0.625rem;
+}
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1.25rem;
+}
+.card-img {
+ width: 100%;
+ border-radius: calc(3px);
+}
+.card-img-top {
+ width: 100%;
+ border-radius: calc(3px);
+}
+.card-img-bottom {
+ width: 100%;
+}
+.card-deck {
+ display: flex;
+ flex-direction: column;
+}
+.card-deck .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .card-deck {
+ flex-flow: row wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+ }
+ .card-deck .card {
+ display: flex;
+ flex: 1 0 0%;
+ flex-direction: column;
+ margin-right: 15px;
+ margin-bottom: 0;
+ margin-left: 15px;
+ }
+}
+.card-deck nav.pager-nav {
+ width: 100%;
+}
+.card-group {
+ display: flex;
+ flex-direction: column;
+}
+.card-group > .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .card-group {
+ flex-flow: row wrap;
+ }
+ .card-group > .card {
+ flex: 1 0 0%;
+ margin-bottom: 0;
+ }
+ .card-group > .card + .card {
+ margin-left: 0;
+ border-left: 0;
+ }
+ .card-group > .card:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:first-child .card-img-top,
+ .card-group > .card:first-child .card-header {
+ border-top-right-radius: 0;
+ }
+ .card-group > .card:first-child .card-img-bottom,
+ .card-group > .card:first-child .card-footer {
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:last-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+ .card-group > .card:last-child .card-img-top,
+ .card-group > .card:last-child .card-header {
+ border-top-left-radius: 0;
+ }
+ .card-group > .card:last-child .card-img-bottom,
+ .card-group > .card:last-child .card-footer {
+ border-bottom-left-radius: 0;
+ }
+ .card-group > .card:only-child {
+ border-radius: 4px;
+ }
+ .card-group > .card:only-child .card-img-top,
+ .card-group > .card:only-child .card-header {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+ .card-group > .card:only-child .card-img-bottom,
+ .card-group > .card:only-child .card-footer {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ }
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) {
+ border-radius: 0;
+ }
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer {
+ border-radius: 0;
+ }
+}
+.card-columns .card {
+ margin-bottom: 0.75rem;
+}
+@media (min-width: 768px) {
+ .card-columns {
+ column-count: 3;
+ column-gap: 1.25rem;
+ }
+ .card-columns .card {
+ display: inline-block;
+ width: 100%;
+ }
+}
diff --git a/VARTHEME_SUBTHEME/less/component/card.component.less b/VARTHEME_SUBTHEME/less/component/card.component.less
new file mode 100644
index 0000000..b2c8749
--- /dev/null
+++ b/VARTHEME_SUBTHEME/less/component/card.component.less
@@ -0,0 +1,280 @@
+// Bootstrap card component.
+// -----------------------------------------------------------------------------
+@import "../../bootstrap/less/variables.less"; // Bootstrap variables.
+@import "../../bootstrap/less/mixins.less"; // Bootstrap mixins.
+@import "../variables.less"; // VARTHEME_SUBTHEME variables.
+@import "../mixins.less"; // VARTHEME_SUBTHEME mixins.
+// -----------------------------------------------------------------------------
+
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: @card-bg;
+ background-clip: border-box;
+ border: @card-border-width solid @card-border-color;
+ border-radius: @card-border-radius;
+
+ > hr {
+ margin-right: 0;
+ margin-left: 0;
+ }
+
+ > .list-group:first-child {
+ .list-group-item:first-child {
+ border-radius: @card-border-radius;
+ }
+ }
+
+ > .list-group:last-child {
+ .list-group-item:last-child {
+ border-radius: @card-border-radius;
+ }
+ }
+}
+
+.card-body {
+ // Enable `flex-grow: 1` for decks and groups so that card blocks take up
+ // as much space as possible, ensuring footers are aligned to the bottom.
+ flex: 1 1 auto;
+ padding: @card-spacer-x;
+}
+
+.card-title {
+ margin-bottom: @card-spacer-y;
+}
+
+.card-subtitle {
+ margin-top: -(@card-spacer-y / 2);
+ margin-bottom: 0;
+}
+
+.card-text:last-child {
+ margin-bottom: 0;
+}
+
+.card-link {
+ &::hover {
+ text-decoration: none;
+ }
+
+ + .card-link {
+ margin-left: @card-spacer-x;
+ }
+}
+
+//
+// Optional textual caps
+//
+
+.card-header {
+ padding: @card-spacer-y @card-spacer-x;
+ margin-bottom: 0; // Removes the default margin-bottom of <hN>
+ background-color: @card-cap-bg;
+ border-bottom: @card-border-width solid @card-border-color;
+
+ &:first-child {
+ border-radius: @card-inner-border-radius @card-inner-border-radius 0 0;
+ }
+
+ + .list-group {
+ .list-group-item:first-child {
+ border-top: 0;
+ }
+ }
+}
+
+.card-footer {
+ padding: @card-spacer-y @card-spacer-x;
+ background-color: @card-cap-bg;
+ border-top: @card-border-width solid @card-border-color;
+
+ &:last-child {
+ border-radius: 0 0 @card-inner-border-radius @card-inner-border-radius;
+ }
+}
+
+
+//
+// Header navs
+//
+
+.card-header-tabs {
+ margin-right: -(@card-spacer-x / 2);
+ margin-bottom: -@card-spacer-y;
+ margin-left: -(@card-spacer-x / 2);
+ border-bottom: 0;
+}
+
+.card-header-pills {
+ margin-right: -(@card-spacer-x / 2);
+ margin-left: -(@card-spacer-x / 2);
+}
+
+// Card image
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: @card-img-overlay-padding;
+}
+
+.card-img {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ border-radius: @card-inner-border-radius;
+}
+
+// Card image caps
+.card-img-top {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ border-radius: @card-inner-border-radius;
+}
+
+.card-img-bottom {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ @border-radius: @card-inner-border-radius;
+}
+
+
+// Card deck
+
+.card-deck {
+ display: flex;
+ flex-direction: column;
+
+ .card {
+ margin-bottom: @card-deck-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ flex-flow: row wrap;
+ margin-right: -@card-deck-margin;
+ margin-left: -@card-deck-margin;
+
+ .card {
+ display: flex;
+ // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+ flex: 1 0 0%;
+ flex-direction: column;
+ margin-right: @card-deck-margin;
+ margin-bottom: 0; // Override the default
+ margin-left: @card-deck-margin;
+ }
+ }
+
+ nav.pager-nav {
+ width: 100%;
+ }
+}
+
+
+//
+// Card groups
+//
+
+.card-group {
+ display: flex;
+ flex-direction: column;
+
+ // The child selector allows nested `.card` within `.card-group`
+ // to display properly.
+ > .card {
+ margin-bottom: @card-group-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ flex-flow: row wrap;
+ // The child selector allows nested `.card` within `.card-group`
+ // to display properly.
+ > .card {
+ // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+ flex: 1 0 0%;
+ margin-bottom: 0;
+
+ + .card {
+ margin-left: 0;
+ border-left: 0;
+ }
+
+ // Handle rounded corners
+ &:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+
+ .card-img-top,
+ .card-header {
+ border-top-right-radius: 0;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-right-radius: 0;
+ }
+ }
+
+ &:last-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+
+ .card-img-top,
+ .card-header {
+ border-top-left-radius: 0;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-left-radius: 0;
+ }
+ }
+
+ &:only-child {
+ border-radius: @card-border-radius;
+
+ .card-img-top,
+ .card-header {
+ border-top-left-radius: @card-border-radius;
+ border-top-right-radius: @card-border-radius;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-left-radius: @card-border-radius;
+ border-bottom-right-radius: @card-border-radius;
+ }
+ }
+
+ &:not(:first-child):not(:last-child):not(:only-child) {
+ border-radius: 0;
+
+ .card-img-top,
+ .card-img-bottom,
+ .card-header,
+ .card-footer {
+ border-radius: 0;
+ }
+ }
+ }
+ }
+}
+
+
+//
+// Columns
+//
+
+.card-columns {
+ .card {
+ margin-bottom: @card-columns-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ column-count: @card-columns-count;
+ column-gap: @card-columns-gap;
+
+ .card {
+ display: inline-block; // Don't let them vertically span multiple columns
+ width: 100%; // Don't let their width change
+ }
+ }
+}
diff --git a/VARTHEME_SUBTHEME/less/variables.less b/VARTHEME_SUBTHEME/less/variables.less
index 14daad8..12d77e9 100644
--- a/VARTHEME_SUBTHEME/less/variables.less
+++ b/VARTHEME_SUBTHEME/less/variables.less
@@ -76,7 +76,7 @@
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
//** Load fonts from this directory.
-@icon-font-path: "../bootstrap/fonts/";
+@icon-font-path: "../../bootstrap/fonts/";
//** File name for all font files.
@icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
@@ -855,6 +855,10 @@
//** Horizontal line color.
@hr-border: @gray-lighter;
+// =============================================================================
+// Custom Vartheme variables.
+// =============================================================================
+
// Media query variables.
@mobile: ~"screen and (max-width: @{screen-xs-max})";
@tablet: ~"screen and (min-width: @{screen-sm-min})";
@@ -862,8 +866,25 @@
@wide: ~"screen and (min-width: @{screen-lg-min})";
@grid-breakpoint: ~"screen and (min-width: @{grid-float-breakpoint})";
-// Set the proper directory for the Bootstrap Glyphicon font.
-@icon-font-path: '../../bootstrap/fonts/';
+// Card bootstrap3 back-ported from bootstrap4.
+@card-spacer-y: 0.75rem;
+@card-spacer-x: 1.25rem;
+@card-border-width: 1px;
+@card-border-radius: @border-radius-base;
+@card-border-color: rgba(red(@gray-base), green(@gray-base), blue(@gray-base), 0.125);
+@card-inner-border-radius: calc(@card-border-radius - @card-border-width);
+@card-cap-bg: rgba(red(@gray-base), green(@gray-base), blue(@gray-base), 0.03);
+@card-bg: #fff;
+
+@card-img-overlay-padding: 1.25rem;
+
+@card-group-margin: floor(@grid-gutter-width/2);
+@card-deck-margin: @card-group-margin;
+
+@card-columns-count: 3;
+@card-columns-gap: 1.25rem;
+@card-columns-margin: @card-spacer-y;
+
// Footer wrapper background color.
@footer-wrapper-bg: #f2f2f2;
diff --git a/css/component/card.component.css b/css/component/card.component.css
new file mode 100644
index 0000000..f0f7c15
--- /dev/null
+++ b/css/component/card.component.css
@@ -0,0 +1,194 @@
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: #fff;
+ background-clip: border-box;
+ border: 1px solid rgba(0, 0, 0, 0.125);
+ border-radius: 4px;
+}
+.card > hr {
+ margin-right: 0;
+ margin-left: 0;
+}
+.card > .list-group:first-child .list-group-item:first-child {
+ border-radius: 4px;
+}
+.card > .list-group:last-child .list-group-item:last-child {
+ border-radius: 4px;
+}
+.card-body {
+ flex: 1 1 auto;
+ padding: 1.25rem;
+}
+.card-title {
+ margin-bottom: 0.75rem;
+}
+.card-subtitle {
+ margin-top: -0.375rem;
+ margin-bottom: 0;
+}
+.card-text:last-child {
+ margin-bottom: 0;
+}
+.card-link::hover {
+ text-decoration: none;
+}
+.card-link + .card-link {
+ margin-left: 1.25rem;
+}
+.card-header {
+ padding: 0.75rem 1.25rem;
+ margin-bottom: 0;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-header:first-child {
+ border-radius: calc(3px) calc(3px) 0 0;
+}
+.card-header + .list-group .list-group-item:first-child {
+ border-top: 0;
+}
+.card-footer {
+ padding: 0.75rem 1.25rem;
+ background-color: rgba(0, 0, 0, 0.03);
+ border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+.card-footer:last-child {
+ border-radius: 0 0 calc(3px) calc(3px);
+}
+.card-header-tabs {
+ margin-right: -0.625rem;
+ margin-bottom: -0.75rem;
+ margin-left: -0.625rem;
+ border-bottom: 0;
+}
+.card-header-pills {
+ margin-right: -0.625rem;
+ margin-left: -0.625rem;
+}
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1.25rem;
+}
+.card-img {
+ width: 100%;
+ border-radius: calc(3px);
+}
+.card-img-top {
+ width: 100%;
+ border-radius: calc(3px);
+}
+.card-img-bottom {
+ width: 100%;
+}
+.card-deck {
+ display: flex;
+ flex-direction: column;
+}
+.card-deck .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .card-deck {
+ flex-flow: row wrap;
+ margin-right: -15px;
+ margin-left: -15px;
+ }
+ .card-deck .card {
+ display: flex;
+ flex: 1 0 0%;
+ flex-direction: column;
+ margin-right: 15px;
+ margin-bottom: 0;
+ margin-left: 15px;
+ }
+}
+.card-deck nav.pager-nav {
+ width: 100%;
+}
+.card-group {
+ display: flex;
+ flex-direction: column;
+}
+.card-group > .card {
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .card-group {
+ flex-flow: row wrap;
+ }
+ .card-group > .card {
+ flex: 1 0 0%;
+ margin-bottom: 0;
+ }
+ .card-group > .card + .card {
+ margin-left: 0;
+ border-left: 0;
+ }
+ .card-group > .card:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:first-child .card-img-top,
+ .card-group > .card:first-child .card-header {
+ border-top-right-radius: 0;
+ }
+ .card-group > .card:first-child .card-img-bottom,
+ .card-group > .card:first-child .card-footer {
+ border-bottom-right-radius: 0;
+ }
+ .card-group > .card:last-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+ .card-group > .card:last-child .card-img-top,
+ .card-group > .card:last-child .card-header {
+ border-top-left-radius: 0;
+ }
+ .card-group > .card:last-child .card-img-bottom,
+ .card-group > .card:last-child .card-footer {
+ border-bottom-left-radius: 0;
+ }
+ .card-group > .card:only-child {
+ border-radius: 4px;
+ }
+ .card-group > .card:only-child .card-img-top,
+ .card-group > .card:only-child .card-header {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+ .card-group > .card:only-child .card-img-bottom,
+ .card-group > .card:only-child .card-footer {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ }
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) {
+ border-radius: 0;
+ }
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header,
+ .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer {
+ border-radius: 0;
+ }
+}
+.card-columns .card {
+ margin-bottom: 0.75rem;
+}
+@media (min-width: 768px) {
+ .card-columns {
+ column-count: 3;
+ column-gap: 1.25rem;
+ }
+ .card-columns .card {
+ display: inline-block;
+ width: 100%;
+ }
+}
diff --git a/css/theme/betterlogin.theme.css b/css/theme/betterlogin.theme.css
index df26df4..dffab00 100644
--- a/css/theme/betterlogin.theme.css
+++ b/css/theme/betterlogin.theme.css
@@ -29,7 +29,6 @@
#auth-box .user-form .form-control {
max-width: 100%;
}
-
#auth-box .block-title {
text-align: center;
background: #eeeeee;
@@ -48,4 +47,4 @@
}
#auth-box .user-login-form {
text-align: left;
-} \ No newline at end of file
+}
diff --git a/less/component/card.component.less b/less/component/card.component.less
new file mode 100644
index 0000000..937b9bb
--- /dev/null
+++ b/less/component/card.component.less
@@ -0,0 +1,280 @@
+// Bootstrap card component.
+// -----------------------------------------------------------------------------
+@import "../../bootstrap/less/variables.less"; // Bootstrap variables.
+@import "../../bootstrap/less/mixins.less"; // Bootstrap mixins.
+@import "../variables.less"; // Vartheme variables.
+@import "../mixins.less"; // Vartheme mixins.
+// -----------------------------------------------------------------------------
+
+.card {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ word-wrap: break-word;
+ background-color: @card-bg;
+ background-clip: border-box;
+ border: @card-border-width solid @card-border-color;
+ border-radius: @card-border-radius;
+
+ > hr {
+ margin-right: 0;
+ margin-left: 0;
+ }
+
+ > .list-group:first-child {
+ .list-group-item:first-child {
+ border-radius: @card-border-radius;
+ }
+ }
+
+ > .list-group:last-child {
+ .list-group-item:last-child {
+ border-radius: @card-border-radius;
+ }
+ }
+}
+
+.card-body {
+ // Enable `flex-grow: 1` for decks and groups so that card blocks take up
+ // as much space as possible, ensuring footers are aligned to the bottom.
+ flex: 1 1 auto;
+ padding: @card-spacer-x;
+}
+
+.card-title {
+ margin-bottom: @card-spacer-y;
+}
+
+.card-subtitle {
+ margin-top: -(@card-spacer-y / 2);
+ margin-bottom: 0;
+}
+
+.card-text:last-child {
+ margin-bottom: 0;
+}
+
+.card-link {
+ &::hover {
+ text-decoration: none;
+ }
+
+ + .card-link {
+ margin-left: @card-spacer-x;
+ }
+}
+
+//
+// Optional textual caps
+//
+
+.card-header {
+ padding: @card-spacer-y @card-spacer-x;
+ margin-bottom: 0; // Removes the default margin-bottom of <hN>
+ background-color: @card-cap-bg;
+ border-bottom: @card-border-width solid @card-border-color;
+
+ &:first-child {
+ border-radius: @card-inner-border-radius @card-inner-border-radius 0 0;
+ }
+
+ + .list-group {
+ .list-group-item:first-child {
+ border-top: 0;
+ }
+ }
+}
+
+.card-footer {
+ padding: @card-spacer-y @card-spacer-x;
+ background-color: @card-cap-bg;
+ border-top: @card-border-width solid @card-border-color;
+
+ &:last-child {
+ border-radius: 0 0 @card-inner-border-radius @card-inner-border-radius;
+ }
+}
+
+
+//
+// Header navs
+//
+
+.card-header-tabs {
+ margin-right: -(@card-spacer-x / 2);
+ margin-bottom: -@card-spacer-y;
+ margin-left: -(@card-spacer-x / 2);
+ border-bottom: 0;
+}
+
+.card-header-pills {
+ margin-right: -(@card-spacer-x / 2);
+ margin-left: -(@card-spacer-x / 2);
+}
+
+// Card image
+.card-img-overlay {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: @card-img-overlay-padding;
+}
+
+.card-img {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ border-radius: @card-inner-border-radius;
+}
+
+// Card image caps
+.card-img-top {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ border-radius: @card-inner-border-radius;
+}
+
+.card-img-bottom {
+ width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
+ @border-radius: @card-inner-border-radius;
+}
+
+
+// Card deck
+
+.card-deck {
+ display: flex;
+ flex-direction: column;
+
+ .card {
+ margin-bottom: @card-deck-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ flex-flow: row wrap;
+ margin-right: -@card-deck-margin;
+ margin-left: -@card-deck-margin;
+
+ .card {
+ display: flex;
+ // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+ flex: 1 0 0%;
+ flex-direction: column;
+ margin-right: @card-deck-margin;
+ margin-bottom: 0; // Override the default
+ margin-left: @card-deck-margin;
+ }
+ }
+
+ nav.pager-nav {
+ width: 100%;
+ }
+}
+
+
+//
+// Card groups
+//
+
+.card-group {
+ display: flex;
+ flex-direction: column;
+
+ // The child selector allows nested `.card` within `.card-group`
+ // to display properly.
+ > .card {
+ margin-bottom: @card-group-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ flex-flow: row wrap;
+ // The child selector allows nested `.card` within `.card-group`
+ // to display properly.
+ > .card {
+ // Flexbugs #4: https://github.com/philipwalton/flexbugs#4-flex-shorthand-declarations-with-unitless-flex-basis-values-are-ignored
+ flex: 1 0 0%;
+ margin-bottom: 0;
+
+ + .card {
+ margin-left: 0;
+ border-left: 0;
+ }
+
+ // Handle rounded corners
+ &:first-child {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+
+ .card-img-top,
+ .card-header {
+ border-top-right-radius: 0;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-right-radius: 0;
+ }
+ }
+
+ &:last-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+
+ .card-img-top,
+ .card-header {
+ border-top-left-radius: 0;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-left-radius: 0;
+ }
+ }
+
+ &:only-child {
+ border-radius: @card-border-radius;
+
+ .card-img-top,
+ .card-header {
+ border-top-left-radius: @card-border-radius;
+ border-top-right-radius: @card-border-radius;
+ }
+ .card-img-bottom,
+ .card-footer {
+ border-bottom-left-radius: @card-border-radius;
+ border-bottom-right-radius: @card-border-radius;
+ }
+ }
+
+ &:not(:first-child):not(:last-child):not(:only-child) {
+ border-radius: 0;
+
+ .card-img-top,
+ .card-img-bottom,
+ .card-header,
+ .card-footer {
+ border-radius: 0;
+ }
+ }
+ }
+ }
+}
+
+
+//
+// Columns
+//
+
+.card-columns {
+ .card {
+ margin-bottom: @card-columns-margin;
+ }
+
+ @media (min-width: @screen-sm) {
+ column-count: @card-columns-count;
+ column-gap: @card-columns-gap;
+
+ .card {
+ display: inline-block; // Don't let them vertically span multiple columns
+ width: 100%; // Don't let their width change
+ }
+ }
+}
diff --git a/less/variables.less b/less/variables.less
index fabd887..8737f7c 100644
--- a/less/variables.less
+++ b/less/variables.less
@@ -76,7 +76,7 @@
//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
//** Load fonts from this directory.
-@icon-font-path: "../bootstrap/fonts/";
+@icon-font-path: "../../bootstrap/fonts/";
//** File name for all font files.
@icon-font-name: "glyphicons-halflings-regular";
//** Element ID within SVG icon file.
@@ -855,6 +855,10 @@
//** Horizontal line color.
@hr-border: @gray-lighter;
+// =============================================================================
+// Custom Vartheme variables.
+// =============================================================================
+
// Media query variables.
@mobile: ~"screen and (max-width: @{screen-xs-max})";
@tablet: ~"screen and (min-width: @{screen-sm-min})";
@@ -862,8 +866,25 @@
@wide: ~"screen and (min-width: @{screen-lg-min})";
@grid-breakpoint: ~"screen and (min-width: @{grid-float-breakpoint})";
-// Set the proper directory for the Bootstrap Glyphicon font.
-@icon-font-path: '../../bootstrap/fonts/';
+// Card bootstrap3 back-ported from bootstrap4.
+@card-spacer-y: 0.75rem;
+@card-spacer-x: 1.25rem;
+@card-border-width: 1px;
+@card-border-radius: @border-radius-base;
+@card-border-color: rgba(red(@gray-base), green(@gray-base), blue(@gray-base), 0.125);
+@card-inner-border-radius: calc(@card-border-radius - @card-border-width);
+@card-cap-bg: rgba(red(@gray-base), green(@gray-base), blue(@gray-base), 0.03);
+@card-bg: #fff;
+
+@card-img-overlay-padding: 1.25rem;
+
+@card-group-margin: floor(@grid-gutter-width/2);
+@card-deck-margin: @card-group-margin;
+
+@card-columns-count: 3;
+@card-columns-gap: 1.25rem;
+@card-columns-margin: @card-spacer-y;
+
// Footer wrapper background color.
@footer-wrapper-bg: #f2f2f2;
diff --git a/vartheme.info.yml b/vartheme.info.yml
index 57ce394..4e7aa4a 100755
--- a/vartheme.info.yml
+++ b/vartheme.info.yml
@@ -45,6 +45,7 @@ libraries:
# Vartheme custom theme, layout, and component libraries.
- vartheme/navbar-admin
- vartheme/bs-callouts
+ - vartheme/card
- vartheme/outside-in
- vartheme/edge2edge
- vartheme/equal-height
diff --git a/vartheme.libraries.yml b/vartheme.libraries.yml
index 40030ef..3f8c50c 100644
--- a/vartheme.libraries.yml
+++ b/vartheme.libraries.yml
@@ -104,6 +104,12 @@ bs-callouts:
css:
component:
css/component/bs-callouts.component.css: {}
+
+# Vartheme bootstrap card component.
+card:
+ css:
+ component:
+ css/component/card.component.css: {}
# Vartheme Outside in component library.
outside-in: