How to float li elements inside multi column list - html

I have the following HTML:
<ul class="baseList">
<li>
<ul class="baseListColumn">
<li>10.09</li>
<li>My title is here</li>
<li>Author</li>
</ul>
</li>
</ul>
with the following css:
.baseList {
border: 1px solid #F00;
}
.baseListColumn {
-moz-column-count:3;
-webkit-column-count:3;
column-count:3;
-moz-column-gap: 10px;
-webkit-column-gap: 10px;
column-gap: 10px;
}
My problem is, that this centers the content of every li of baseListColumn and gives every column the same width. I would like to make the columns fit it's content apart from the last li element (Author) and float the content of the last li element right.
This is what happens with the current code: http://jsfiddle.net/aLGRJ/1/
10.09 My title is here Author
asdfasdfasdfasdf My title is here abababa Author
In fiddle you can even see what happens if the width of the root li is big enough while the equal splitting of the columns is too small to contain some of the content.
This is what I would like to have:
10.09 My title is here Author
asdfasdfasdfasdf My title is here abababa Author
I can't guarantee that all the columns will always have the same length otherwise I would use absolute positioning and at the same time I don't want to reserve too much unnecessary space for the first column for example. Note I'm planning to use this for lists with more columns than just 3 as well.
Is this one of the cases where a table would be the better solution? Anyways I hope someone can help me, and if there is a better solution to this, I'm always open for suggestions.

It looks like a table would be a better solution, not because of the display properties, but because of the nature of your content (remember, organizing content is still the responsibility of HTML).
Take a look at this page.
While most of the points are generally agreeable, I tend to focus on two things:
Don’t Use Faux Tables (<p>, <div>, etc.)
Tables Should Be Filterable & Sortable (If more then just a few rows)
You can generate all of the CSS yourself... or, use your favorite ECMAScript library to make short work of styling.

Related

Can you "line-break" a table using CSS by width or number of columns?

I have an HTML table with 17 columns over 2 header rows and 1 body row. On most desktop views, this table fits nicely with my design, but on small screens the table overhangs its parent element and a significant amount of horizontal scroll is created.
I was wondering if there's a way in CSS/HTML/JS to catch a table going over a certain width, or counting a number of columns (or any other sensible way of doing it), and causing it to 'break' over into a new line, the same way a line break would be added to a paragraph. I want to catch this programatically (rather than just rewriting the table to multiple tables) as the large-screen experience is dramatically better without this hypothetical column-line break.
Ideally I'd like to keep the css definitions of table-cell etc (as in, not just make everything display: block and be done with it).
To add to the complications, some of the header cells in the top row span two columns. I'm hoping a solution can be found that either doesn't break those cells, or copies the text in the cell to both columns after a break is made.
This is all inside the Foundation 6 framework, if there's any tools there that I've missed. I tried using Foundation's <table class="stack">, but it doesn't work - it only shows the body row, I think because some of the header cells span multiple columns.
You can try to use css-grid with media-query
More
Example
HTML
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<li>E</li>
<li>F</li>
</ul>
CSS
ul {
display: grid;
grid-template-columns: 140px 140px 140px 140px;
grid-gap: 10px;
}
#media only screen and (max-width: 800px) {
ul {
grid-template-columns: 200px 200px;
}
}
Having done more research, I can see there's no 'proper' way to do what I wanted to do. In my case, the simplest way to achieve the desired result visually was to make each column/column pair its own table, and then make those tables display as blocks and float to the left. This isn't great semantically (a new table for every major data point), but it's for an internal tool to be used by a small team, so I'm not spending more time on this.

Responsive text-align based on position

I think the answer to this is no but, before I make more drastic changes, I want to ensure I haven't missed something.
Is there a means, via CSS only, to alter the justification of an element and its children based on whether it's orientated more towards the left or right of the screen?
There's no straight property for this but I'm seeing if I've missed some hack-like method perhaps involving pseudo selectors or elements.
Demonstration of current predicament:
I have a <ul> nav bar that provides a mixture of <a> links and some nested <ul> containers for drop down menus on hover. Pretty standard and works fine on wider screens:
If there's less screen space available, the nav wraps to the next line as intended. This is a desirable outcome. However, sometimes the drop-down menus can be truncated off-screen, which is not very desirable:
Rather than providing a vastly different style for mobile devices (my fallback plan is to present the drop-down menus as dialog-like choices via postion: fixed on smaller screens, rather than position: absolute as they are now), I could fix my situation through my elements being aware of their adventure off-screen and the need to both text-align: right and to possibly adjust their absolute positioning to anchor to the right of the parent <li> rather than the left, as they are now:
I can manage this via javascript but I've enough listener events already occurring and want to provide a more elegant response that avoids javascript. If there's no css-only method I might use the fixed position alternative as a plan b instead.
Clarifications:
While I was originally expecting to use media queries to solve this predicament on mobile devices, I realised that, though it is only apparent on smaller screen sizes for me, this is not something I can take for granted.
For example, the number of nav items may grow in the future and could present this situation at any screen size. It just needs a drop-down menu to be at the screen right.
I also cannot guarantee that a device I've yet to test is not replicating the issue at a size I hadn't expected it to.
My point being that I don't see a way I can rely on screen size media queries. I think my solution, if any, needs to responsive to the position of the element on the screen — which is why I think I may be out-of-luck for a non-javascript solution.
Secondly: Assume content is dynamic and, like any capable page, elements that should dynamically change properties to accommodate this, do (such as nav item order, count, widths, etc.). I should refer anyone looking for finer caveats in this area to the original question: Is there a means, via CSS only, to alter the justification of an element and its children based on whether it's orientated more towards the left or right of the screen?
Sample Code:
As requested, here is the sample code. I don't think it's a good idea including it in this scenario (though understand it's importance in most questions) as it detracts from the question being mostly unrelated to my specific code and far more related to questioning the ability of css to dynamically modify an attribute(s) based on screen position or awareness of screen edges — in any scenario — hence my preference for illustrating the question.
The code is a simplified version of my own but the question could have been asked with almost any variation of a standard, familiar <ul> navigation menu that provides drop-downs via :hover in CSS.
With that in mind, if you are trying to solve the question by working through my code then I may have described my predicament poorly. I believe I'm pretty well versed in the extents that CSS can currently be pushed to and believe the answer to be 'it's not possible without javascript' but am just ensuring I haven't missed a clever workaround/hack for dynamically altering element attributes via CSS based on screen-position (sorry for repetition of the question - I just want to ensure it's understood, following some comments). Thanks.
<ul class="nav nav__container">
<li><a class='nav nav__item' href="#">Standard Link</a></li>
<li><a class='nav nav__item' href="#">Standard Link</a></li>
<li><a class='nav nav__item' href="#">Standard Link</a></li>
<li><a class='nav nav__item' href="#">Standard Link</a></li>
<li class='nav nav__item nav__item--dropdown'><li>Dropdown Label</li>
<ul class='nav nav__dropdown'>
<li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
<li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
<li><a class='nav nav__item nav__item--dditem' href="#">Dropdown Link</a></li>
</ul>
</li>
</ul>
There is indeed a CSS only solution which works exactly as you've presented in your question's attached images. However it may not be a truly complete answer as it depends on one crucial factor - that all your top level menu items have the same width. Now this is the case shown in your attached images, but may not be true of your actual implementation.
Using the CSS3 nth-child selector with the n variable you can target every 3rd, or 4th, etc top level menu item. Targeted items can easily be styled to have their dropdown menus align right. Thus, for a hard-coded solution on a single screen you would count the number of top level menu items in a row and set that as your n multiplier. For example, if your menu wrapped after 6 items, to style the last item of each row you would set something like:
.top-level-item:nth-child(6n) > .dropdown-container > .sub-item {
float: right;
clear: right;
}
or however your actual implementation needs to style a right aligned menu.
Of course, this depends on all menu items having the same width. If your menu has more than 2 rows and your menu items have varying widths then you may have a varying number of elements in each row, in which case the nth-child selector wouldn't necessarily target the end child of each row.
Now to make this work for any screen size, if all top level items have the same fixed width, we then need to find out how many items there will be per row regardless of the window's width. Sadly, calc() is too limited for this application. However, if the top items have a fixed width and we know what that width is, we can use a series of #media statements for each case.
For example, lets say that with margins and width together, each top level item has a width of 230px. This means that if the window's width is less than 230 * 3 = 690px, there will be 2 items in each row. If the window's width is less than 230 * 4 = 920px and greater than 690px there will be 3 items in each row. And so on, to the largest window size you think you'll need. Using the above nth-child example, the series of media queries to target each row size would look something like:
#media (max-width: 690px) {
/* less than 3 items per row */
.top-level-item:nth-child(2n) > .dropdown-container > .sub-item {
float: right;
clear: right;
}
}
#media (max-width: 920px) and (min-width: 691px) {
/* less than 4 items per row */
.top-level-item:nth-child(3n) > .dropdown-container > .sub-item {
float: right;
clear: right;
}
}
#media (max-width: 1150px) and (min-width: 921px) {
/* less than 5 items per row */
.top-level-item:nth-child(4n) > .dropdown-container > .sub-item {
float: right;
clear: right;
}
}
...
/* and so on */
A pen that shows an implementation of this is at https://codepen.io/jla-/pen/GYJQMq. Note that the JavaScript is only there to toggle the dropdown menus when they're clicked.
For top level menu items that have variable width, or if they have the same width but you don't know what value it is, I don't think current CSS is powerful enough to do what you want. Ideally you would do something like .top-level-item:nth-child(calc((100vw/--itemwidth)-(100vw%--itemwidth)) to get the number of items in a row, but I think CSS is a very long way off that sort of power.
May be media query with flex can help you if you use it correctly.. I tried to replicate your problem on jsfiddle.
<div id="menu-container">
<div class="menu"></div>
<div class="menu"></div>
<div class="menu">
<div id="sub-menu-container">
<div class="sub-menu" id="sub-menu1"></div>
<div class="sub-menu" id="sub-menu2"></div>
<div class="sub-menu" id="sub-menu3"></div>
<div class="sub-menu" id="sub-menu4"></div>
</div>
</div>
<div class="menu"></div>
</div>
CSS
.menu{
border-radius:15px;
background-color: #00ab9e;
width:120px;
height:50px;
border: 1px solid #01eae9;
display:inline-block;
margin:5px;
position:relative;
vertical-align:top;
}
#sub-menu-container{
margin-top:50px;
display: flex;
flex-flow: column wrap;
align-items: flex-start;
}
.sub-menu{
border-radius:15px;
background-color: #ffb12a;
width:120px;
height:50px;
border: 1px solid #01eae9;
margin-top:5px;
}
#sub-menu2{
width:150px;
}
#sub-menu3{
width:200px;
}
#media only screen and (max-width: 495px) {
#sub-menu-container {
align-items: flex-end;
}
}
#media only screen and (max-width: 420px) {
#sub-menu-container {
align-items: flex-start;
}
}
https://jsfiddle.net/nimittshah/7bsf1r3v/
Thanks
It looks like the answer to the core question:
Is there a means, via CSS only, to alter the justification of an element and its children based on whether it's orientated more towards the left or right of the screen?
is no.
As a more thorough follow-up answer I thought I'd mention that I'm not going with my original plan B of styling drop-down menus to be fixed at smaller screen sizes. I hinted at this in my question but it's become more apparent that I cannot rely on screen size to determine if a drop-down menu will be truncated in the future. So given that media queries are now ruled out, I need another solution if I want to ensure that I don't provide a sloppy solution to any device.
Which leaves me with javascript. I was trying to avoid this but, at this stage, I would be stubborn to do so given the outcome.
Method
Incase it's of use to anybody else, I used jquery to provide a listener for hovering over drop-down menus. The logic is that all elements of a certain class are guaranteed to have a drop-down menu, comprised of a <ul> of another class. So I can target both easily.
I could check if the drop-down menu is to the right or left of the screen. This would work fine. Being picky, I'd rather the menu stay justified to the left unless it's about 200 pixels from the right of the screen - a safe threshold for my dynamic content. I could go and measure each dropdown width and use that as a threshold if I ever run into issues.
Putting all of this together. If I hover over a dropdown menu and it finds itself to be less than 200 pixels from the right of the screen, it will both justify its menu to the right and absolute position the dropdown menu to the right-most side of its parent menu label/trigger (as I showed in my original illustrations). There are more flexible and shorter versions of doing this and it's also not much more work to do without jquery for anyone avoiding the library:
JS Code
$(nav).on('mouseover', '.dropdown', function() {
var dropdownlist = $(this).children('ul');
var screenWidth = $(window).width();
var parentOffsetLeft = $(this).offset().left;
var spaceRight = screenWidth - parentOffsetLeft;
if (spaceRight < 200) {
$(dropdownlist).css('text-align', 'right');
$(dropdownlist).css('right', '0');
$(dropdownlist).css('left', 'initial');
} else {
$(dropdownlist).css('text-align', 'left');
$(dropdownlist).css('left', '0');
$(dropdownlist).css('right', 'initial');
}
});
Using this javascript, I can recreate the solution illustrated in the question.
Write media-query for your requirement as you want to adjust the text justification. you can change test's justified property inside media-query. use different media-query for different display size according to your requirement, see the example
#media only screen and (max-width: 600px) {
selector {
property : value;
}
}

Ensuring similar block height of horizontally aligned DIVs with unknown content length

On a website i'd like to show products in the following structure:
[IMAGE]
[PRODUCT TITLE]
[PRODUCT ID]
[DETAIL TEXT]
[FEATURE LIST]
[PRICE]
Resulting in a product display such as:
Now, the thing is that there are multiple products on display, just like this one, but sometimes they are aligned next to one another.
The problem is that i would like to make the price appear at the same position (vertical wise) in all blocks. Of course i see only one solution at first - overflow:hidden on the detail text / feature listing. But then i'd end up having content cut off, right?
Another problem is that there should also be a more>> button (expander) that appears if the UL/LI-listing is longer than 4 entries. Just like this:
I thought this through quite often, but i seem to find no proper solution. For one i will never know if an LI will be multiline, as the content might be longer or shorter - and i cannot calculalate this serverside, as the font width/height might vary.
I'd appreciate any constructive input here.
Thank You!
As long as you have a fixed width you could use inline-block mixed with negative margins : http://jsfiddle.net/bymaK/11/
The sad thing is that it works in Chrome, Opera and IE 9 but completely break Firefox as it's management of with:0 and negative margin seem buggy (Added issue #709014 to Bugzilla following this post). The solution is to detect this browser and set the width to 1px for it...
It create a small bug as when you resize there is 1 pixel where the price warp to the next line but not the block but it's a lot less visible that the result otherwise :
<div id="container">
<p>texttexttext</p>
<ul>
<li>texttexttext</li>
<li>texttexttext</li>
<li>texttexttext<Update/li>
<li>texttexttext</li>
<li>more »</li>
<li class="more">more text</li>
<li class="more">Even more text.</li>
</ul>
</div><p class="price">$3993.99</p>
.price
{
height:40px;
display:inline-block;
margin-left: -200px;
margin-right: 200px;
vertical-align: bottom;
font-weight: bold;
}
#container
{
display: inline-block;
margin-right:10px;
position:relative;
width:200px;
padding-bottom:40px;
vertical-align: top;
}
ul
{
list-style-type:disc;
margin-left:30px
}
li.more
{
display: none;
}
$(function(){
$('a.more').click(function(){
$(this).parent('li').hide().nextAll('li').show(200);
});
});
Maybe have the containing div set to position: relative, and then price set to position: absolute; bottom:0? That way, no matter how much text is in the box, the price is always at 0 (or whatever number you set).
Here's a rudimentary example: http://jsfiddle.net/PFwJ6/1/
You might want to use javascript to find the height and display a "click to view more link".
First, create a div over the price div that would contain your "click to see more" link and set it to display:none. Then you can use offsetHeight in javascript to find the height of the div. If the height is over what is acceptable then you would set the div to display:block. That means you can set all of your containing divs to the same height with the price div pinned to the bottom using positioning.
I'm sorry I don't have concrete code for you. I might be able to put some together shortly. But this should point you in the right direction.

Make list item fit its contents

I have the following list in HTML:
<ul>
<li><span class="button">A</span></li>
<li><span class="button">B</span></li>
<li><span class="button">C</span></li>
</ul>
The accompanying CSS. Understand that I want to use differently sized buttons for different lists.
.button
{
background: blue;
padding: 0.5em;
}
The li's do not expand to fit the spans inside of them. This has the effect of throwing off the margin of the whole list, which will be especially important when I turn the list into a horizontal menu.
Also, the reason I have styled spans inside the li's instead of styling the li's themselves is because some of those spans will actually be links.
This great article is drilling into your problem and showing what a good practise is: http://css-tricks.com/keep-margins-out-of-link-lists
That is, if I understood what you were aiming for, your question could be a bit clearer. :)
You must declare the span as an Blockelement with display:block;
Is it the solution for you?

Left, center, and right text

What's the best way to obtain three texts on the same line: one to the left, another in the middle, and the third one to the right?
+---------------------------------------------------------------------+
|Page generated in 1 ms Copyright 2010 Email me|
+---------------------------------------------------------------------+
One text may be longer than the others, but their position must not change. The one in the middle must always be in the middle, regardless of the length of the others.
Doing it with tables would be easy, and I already know how to do that, so "correct" solutions only (using tables for layout is wrong).
EDIT: many people assumed for some reason that I needed to display tabular data over several rows. I'm not sure why they thought it was the case, but:
It will have only one row
It's not tabular data
For this reason a table is inappropriate, and the solution only needs to work with one line.
Taking your question literally, here's how I'd do it.
<div style="position:absolute;text-align:left">Text 1, a bit longer</div>
<div style="position:absolute;width:100%;text-align:center">Text 2</div>
<div style="text-align:right">Text 3</div>
Whether this will work for you in practice, depends on what the texts actually are. Note that if the divs' container is too narrow, the texts will overlap with one another, and not wrap like they would if they were in table cells.
If you want table-like layout behaviour, you have two choices. You can use tables, or you can use the CSS display:table, display:table-cell etc properties. Sadly, the latter is not supported in IE6 or IE7, so probably isn't really usable on the web just yet.
I found a very good way to do this that works even if one or more of the paragraphs will span over multiple lines.
<p style="float: left; width: 33.3%; text-align: left">Page Statistics</p>
<p style="float: left; width: 33.3%; text-align: center;">© 2010</p>
<p style="float: left; width: 33.3%; text-align: right;"><a>Email me</a></p>
you can do this with a unordered list and some CSS, if you want to stay 'semantic' that is
<ul id="text_block">
<li class>Text 1, a bit longer</li>
<li class>Text 2</li>
<li class>Text 3</li>
</ul>
and the CSS
ul#text_block {display: table; margin: 0; padding: 5px;}
ul#text_block li {list-style: none; display: inline; margin: 0 40px 0 0;}
hope this helps
So you want to display three pieces of data, over and over, stacked in a vertical pattern that represents some sort of data, options, etc?
Sounds to me like that's exactly what tables are for.
/* Removed box comment, OP fixed it */
Maybe you need to look at grid design system?
http://www.subtraction.com/2004/12/31/grid-computi
http://www.subtraction.com/pics/0703/grids_are_good.pdf
Or, you always can use float div's, playing by float, width and poisition CSS properties.