AngularJS: Two-column odd/even layout - css

Having a problem trying to get a repeating two-column layout in AngularJS. My dataset is a JSON object of image information. I want to show a two column layout of images. No matter what I tweak, something is wrong in my odd/even logic, but I can't seem to figure it out. What am I doing wrong?
.left {
float: left !important;
width: 50% !important;
}
.right {
float: right !important;
width: 50% !important;
}
.group:after {
content:"";
display: table;
clear: both;
}
img {
max-width: 100%;
height: auto;
}
#media screen and (max-width: 480px) {
.left,
.right {
float: none;
width: auto;
}
}
<div ng-repeat="issue in issues">
<div ng-if="$even" class="group">
<div class="left" ng-if="$even">
<img src="{{ issue.image }}" ng-src="{{ issue.image }}">
</div>
<div class="right" ng-if="$odd">
<img src="{{ issue.image }}" ng-src="{{ issue.image }}">
</div>
</div>
</div>

The issue with code is you had wrap your logic inside
<div ng-if="$even" class="group">
Div which is restricting to show odd logic div.
instead of having two different div, I'd say use ngClassEven & ngClassOdd directive. Also remove the wrapper div which has ng-if="$even" condition.
<div ng-repeat="issue in issues">
<div ng-class-even="'left'" ng-class-odd="'right'">
<img ng-src="{{ issue.image }}">
</div>
</div>

I guess you already got your answer, but still here are some alternatives which may prove useful:
Simply ng-class - it's a little more flexible, so you may find it useful in other cases too. In this case:
<div ng-repeat="issue in issues" ng-class="{left: $even, right: $odd}">
<img ng-src="{{ issue.image }}">
</div>
or
<div ng-repeat="issue in issues" ng-class="$even ? 'left' : 'right'">
<img ng-src="{{ issue.image }}">
</div>
Note that unlike some other properties ng-class can coexist with class in harmony so you could also add class="item" or something similar.
Since it's a styling issue you may want to try to solve it in css. As long as you think IE 6-8 should die you can use the nth-child selector:
:nth-child(odd) { ... }
:nth-child(event) { ... }
Also since both my and Pankaj's answers removed your group class here is some simpler css which you could use instead:
.item {
float: left;
width: 50%;
}
.left {
clear: left;
}
#media screen and (max-width: 480px) {
.item {
float: none;
width: auto;
}
}
Or again if you're not all about IE you could use flexbox (which removes the need for any JS):
.parent {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 0 0 50%;
}
#media screen and (max-width: 480px) {
.item {
flex-basis: 100%;
}
}

Related

How to have 1 column in a flex box fill remaining space

I have the following html:
<div id="inner-container">
<div id="titles">
<div id="main-title">Main title here</div>
<div id="page-title">Page title here</div>
</div>
<nav id="progress-container>
<div id="page-counter">Page count here</div>
<a id="link-to-page-1"></a>
<a id="link-to-page-2"></a>
<a id="link-to-page-3"></a>
<a id="link-to-page-4"></a>
<a id="link-to-page-5"></a>
<a id="link-to-page-6"></a>
</nav>
</div>
and this css:
#inner-container {
display: flex;
}
#titles > div {
width: 100%;
}
#progress-container #page-counter {
float: left;
}
#progress-container a {
display: inline-block;
width: 30px;
height: 12px
border: 3px solid #ffffff;
}
#media (max-width: 900px) {
#progress-container #page-counter {
display: none;
}
}
I would like to add the necessary css flex rules so that #titles occupies the full remaining width, left over by #progress-container.
I have tried:
#titles {
flex-grow: 1;
}
And I've tried various rules for #page-progress, including 'flex-basis: auto' and 'flex-basis: content', but nothing has worked.
Note that I cannot set a fixed width to #progress-container as the number of 'pages' is dynamic and will vary. Also the #page-counter disappears below 900px.
If anyone has any ideas, I'd like to hear them!
try adding flex: 1; in #titles.
learn about flex properties over here
#titles {
flex: 1;
}
codepen link

BEM: Best way to have container and row?

I have the following setup for a content block in BEM:
SCSS
.container {
width: 960px;
margin: 0 auto;
}
.row {
width: 100%;
float: left;
}
.latest-news__container {
#extend .container;
}
.latest-news__row {
#extend .row;
}
Which compiles to:
.container, .latest-news__container {
width: 960px;
margin: 0 auto;
}
.row, .latest-news__row {
width: 100%;
float: left;
}
My HTML
<div class="latest-news">
<div class="latest-news__container">
<div class="latest-news__row">
<div class="latest-news__image"></div>
<div class="latest-news__content"></div>
</div>
</div>
</div>
Question:
Is using #extend for the .container and .row a good idea in order to keep the class name for the elements as per the block name? Or should I just have .container and .row? Then have another #extend for other blocks and so on.
Take a look at mixes concept (when different blocks or elements are mixed on the same DOM node): https://en.bem.info/methodology/key-concepts/#mix and https://en.bem.info/methodology/css/#mixes
So your markup may look like this (which will give you possibility to avoid #extend at all):
<div class="latest-news container">
<div class="latest-news__item row">
<div class="latest-news__image"></div>
<div class="latest-news__content"></div>
</div>
</div>

responsive set middle column on top

So i have a traditional three column lay-out. The left column is like a toolbox column, the middle column is the "dynamic content" column and the right one is like a summary of data column.
What i want to achieve is that as soon as some responsiveness is going on that the center column will be on top. This will be the most important part of the website and thus should be on top. I cant seem to get this to work with bootstrap. This is my lay-out:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<!-- column: left -->
<div class="col-md-2" id="sidebarleft">left </div>
<!-- column: center-->
<div class="col-md-8" id="main">middle</div>
<!-- column: right -->
<div class="col-md-2" id="sidebarright">right</div>
</div>
</div>
So how would i go about achieving this?
Thanks!
This should do the trick.
So the layout is intact when the browser is using Bootstrap's "md" viewport, however when made smaller (so "sm" and "xs") the middle column is at the top followed by the left and right.
<div class="container">
<!-- Example row of columns -->
<div class="row">
<!-- column: center-->
<div class="col-md-8 col-md-push-2" id="main">middle</div>
<!-- column: left -->
<div class="col-md-2 col-md-pull-8" id="sidebarleft">left </div>
<!-- column: right -->
<div class="col-md-2" id="sidebarright">right</div>
</div>
That's because your HTML is stacking in order of the way it's written.
A good way to achieve this would be to either:
a) Take a dropdown UI approach on the #sidebarleft or, b) Use JS to refactor the layout when responsive. Though, depending how much your site relies on JS, this may not be suitable from a no-js point of view. It would need a fallback. I'm not entire too sure on CSS methods with Bootstrap using the push/pull class selectors.
A jQuery solution would be to store the element ID in a variable and then tell the DOM to remove the element at a certain width. Then, tell it to insertBefore or insertAfter the #sidebarleft element.
var mainContent = $('#main');
var leftSidebar = $('#sidebarleft');
$(window).resize(function() {
if ($(window).width() <= 480) {
mainContent.remove();
mainContent.insertBefore(leftSidebar);
} else if ($(window).width() > 481) {
mainContent.remove();
mainContent.insertAfter(leftSidebar);
}
});
Here's a Pen on the functionality in JS using jQuery.
Resize the screen to less or equal than 480 pixels and watch the main content reorder itself above the sidebar.
I wrote this and worked great for me. The middle column goes to the left on mobile. The 3rd one goes down on tablet.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.container {
width: 100%;
max-width: 1140px;
margin: 15px auto;
}
.col {
margin-bottom: 10px
}
.rowone {
width: 75%;
float: left;
}
.rowtwo {
width: 24%;
float: right;
}
.middle {
float: right;
width: 66.6%;
background: #fe8a9e
}
.left {
float: left;
width: 32%;
background: #64c780
}
.right {
float: left;
width: 100%;
background: #4690ec
}
#media (max-width: 860px) {
.rowone, .rowtwo {
width: 100%;
}
.left {
float: right
}
.middle {
float: left
}
.right .module.long {
height: 218px;
}
}
#media (max-width: 500px) {
.col, .rowone, .rowtwo {
width: 100%;
}
.middle {
float: left
}
.left {
float: right
}
.rowtwo {
float: left
}
}
</style>
</head>
<body>
<div class="container">
<div class="rowone">
<div class="col middle">Middle</div>
<div class="col left">Left</div>
</div>
<div class="rowtwo">
<div class="col right">Right</div>
</div>
</div>
</body>
</html>

Div placement even in a single parent and move the other div to the middle

<div class="sidebar">
<div class="title"></div>
<div class="related"></div>
</div>
<div class="description"></div>
As you can see, there are 2 parent divs, sidebar and description, and 2 child divs within sidebar. I have given css rules for them and looks like this picture below :
Question : how can I make the view like this with those markup without change the markup ? :
*Note : the second will be view if the window's width <= 320px. I have used #media query but the problem is, title and related are within the one parent (sidebar), so it was difficult for me to make them separated and move description in the middle of them.
Thanks
This might not be a smart way, but the code below could be a solution for your problem:
HTML:
<div class="sidebar">
<div class="title"></div>
<div class="description2"> description ...</div>
<div class="related"></div>
</div>
<div class="description"> description ... </div>
CSS:
.description2{
display:none;
}
#media only screen and (max-width: 320px) {
.description{
display:none;
}
.description2{
display:block;
}
}
Hope this helps.
I don't think it can be done keeping the two divs within the sidebar (without using javascript). However you can do it like this which makes more sense to me, as it places the description immediately after the title.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Media query</title>
<style>
.title,
.description,
.related {
background-color: #333;
margin: 5px;
}
#media only screen
and (min-width : 620px) {
.holder {
width: 620px;
}
.title {
float: right;
width: 200px;
height: 200px;
}
.description {
float: left;
width: 400px;
height: 600px;
}
.related {
float: right;
width:200px;
height: 390px;
}
}
</style>
</head>
<body>
<div class="holder">
<div class="title"></div>
<div class="description"></div>
<div class="related"></div>
</div>
</body>
</html>

CSS fill remaining width

I have this header bar.
<div id="header">
<div class="container">
<img src="img/logo.png"/>
<div id="searchBar">
<input type="text" />
</div>
<div class="buttonsHolder">
<div class="button orange inline" id="myAccount">
My Account
</div>
<div class="button red inline" id="basket">
Basket (2)
</div>
</div>
</div>
</div>
I need the searchBar to fill whatever the remaining gap is in the div. How would I do this?
Here's my CSS
#header {
background-color: #323C3E;
width:100%;
}
.button {
padding:22px;
}
.orange {
background-color: #FF5A0B;
}
.red {
background-color: #FF0000;
}
.inline {
display:inline;
}
#searchBar {
background-color: #FFF2BC;
}
Use calc!
https://jsbin.com/wehixalome/edit?html,css,output
HTML:
<div class="left">
100 px wide!
</div><!-- Notice there isn't a space between the divs! *see edit for alternative* --><div class="right">
Fills width!
</div>
CSS:
.left {
display: inline-block;
width: 100px;
background: red;
color: white;
}
.right {
display: inline-block;
width: calc(100% - 100px);
background: blue;
color: white;
}
Update: As an alternative to not having a space between the divs you can set font-size: 0 on the outer element.
You can realize this layout using CSS table-cells.
Modify your HTML slightly as follows:
<div id="header">
<div class="container">
<div class="logoBar">
<img src="http://placehold.it/50x40" />
</div>
<div id="searchBar">
<input type="text" />
</div>
<div class="button orange" id="myAccount">My Account</div>
<div class="button red" id="basket">Basket (2)</div>
</div>
</div>
Just remove the wrapper element around the two .button elements.
Apply the following CSS:
#header {
background-color: #323C3E;
width:100%;
}
.container {
display: table;
width: 100%;
}
.logoBar, #searchBar, .button {
display: table-cell;
vertical-align: middle;
width: auto;
}
.logoBar img {
display: block;
}
#searchBar {
background-color: #FFF2BC;
width: 90%;
padding: 0 50px 0 10px;
}
#searchBar input {
width: 100%;
}
.button {
white-space: nowrap;
padding:22px;
}
Apply display: table to .container and give it 100% width.
For .logoBar, #searchBar, .button, apply display: table-cell.
For the #searchBar, set the width to 90%, which force all the other elements to compute a shrink-to-fit width and the search bar will expand to fill in the rest of the space.
Use text-align and vertical-align in the table cells as needed.
See demo at: http://jsfiddle.net/audetwebdesign/zWXQt/
I know its quite late to answer this, but I guess it will help anyone ahead.
Well using CSS3 FlexBox. It can be acheived.
Make you header as display:flex and divide its entire width into 3 parts. In the first part I have placed the logo, the searchbar in second part and buttons container in last part.
apply justify-content: space-between to the header container and flex-grow:1 to the searchbar.
That's it. The sample code is below.
#header {
background-color: #323C3E;
justify-content: space-between;
display: flex;
}
#searchBar, img{
align-self: center;
}
#searchBar{
flex-grow:1;
background-color: orange;
padding: 10px;
}
#searchBar input {
width: 100%;
}
.button {
padding: 22px;
}
.buttonsHolder{
display:flex;
}
<div id="header" class="d-flex justify-content-between">
<img src="img/logo.png" />
<div id="searchBar">
<input type="text" />
</div>
<div class="buttonsHolder">
<div class="button orange inline" id="myAccount">
My Account
</div>
<div class="button red inline" id="basket">
Basket (2)
</div>
</div>
</div>
This can be achieved by wrapping the image and search bar in their own container and floating the image to the left with a specific width.
This takes the image out of the "flow" which means that any items rendered in normal flow will not adjust their positioning to take account of this.
To make the "in flow" searchBar appear correctly positioned to the right of the image you give it a left padding equal to the width of the image plus a gutter.
The effect is to make the image a fixed width while the rest of the container block is fluidly filled up by the search bar.
<div class="container">
<img src="img/logo.png"/>
<div id="searchBar">
<input type="text" />
</div>
</div>
and the css
.container {
width: 100%;
}
.container img {
width: 50px;
float: left;
}
.searchBar {
padding-left: 60px;
}
in css:
width: -webkit-fill-available
I would probably do something along the lines of
<div id='search-logo-bar'><input type='text'/></div>
with css
div#search-logo-bar {
padding-left:10%;
background:#333 url(logo.png) no-repeat left center;
background-size:10%;
}
input[type='text'] {
display:block;
width:100%;
}
DEMO
http://jsfiddle.net/5MHnt/
Include your image in the searchBar div, it will do the task for you
<div id="searchBar">
<img src="img/logo.png" />
<input type="text" />
</div>
I did a quick experiment after looking at a number of potential solutions all over the place. This is what I ended up with:
http://jsbin.com/hapelawake

Resources