If you want to practise implementing recursive predicates, you could proceed like this using dcg:
matrix_transposed_items(Mss,Xs) :-
   notlonger_than(Mss,Xs),
   phrase(matrix_tconcat(Mss),Xs).
matrix_tconcat([]) --> [].
matrix_tconcat([Cs|Css]) -->
   row_rows_rest_(Cs,Css,Mss),
   matrix_tconcat(Mss).
row_rows_rest_([],Css,[]) --> 
   { emptylists(Css) }.
row_rows_rest_([X|Xs],Xss,[Xs|Mss]) -->
   [X],
   nonemptyrows_rest(Xss,Mss).
nonemptyrows_rest([],[]) --> [].
nonemptyrows_rest([[X|Xs]|Xss],[Xs|Mss]) -->
   [X],
   nonemptyrows_rest(Xss,Mss).
Above code is based on three auxiliary predicates which can be defined like this:
nil_or_cons([]).
nil_or_cons([_|_]).
notlonger_than([],Bs) :-
   nil_or_cons(Bs).
notlonger_than([_|As],[_|Bs]) :-
   notlonger_than(As,Bs).
emptylists([]).
emptylists([[]|Xs]) :-
   emptylists(Xs).
Let's run some queries!  First, we use some quadratic matrix:
?- matrix_transposed_items([[1,2,3],[4,5,6],[7,8,9]],Xs).
Xs = [1,4,7,2,5,8,3,6,9].                            % succeeds deterministically
Next, the non-quadratic use-cases the OP gave:
?- matrix_transposed_items([[a,b],[c,d],[e,f]],Ls).
Ls = [a,c,e,b,d,f].                                  % succeeds deterministically
?- matrix_transposed_items([[1,2,3],[4,5,6]],Ls).
Ls = [1,4,2,5,3,6].                                  % succeeds deterministically
Let's try going the "other direction", too!
?- matrix_transposed_items(Mss,[1,2,3,4,5,6,7,8,9,10]).
  Mss = [[1,2,3,4,5,6,7,8,9,10]]
; Mss = [[1,3,5,7,9],[2,4,6,8,10]]
; Mss = [[1,6],[2,7],[3,8],[4,9],[5,10]]
; Mss = [[1],[2],[3],[4],[5],[6],[7],[8],[9],[10]]
; false.                                             % terminates universally
append/2, or check out its definition in the Prolog library.append/2is definitely a lot cleaner thanflatten/2, so I highly recommend to useappend/2when you want the things you describe. - matappend([[1,2,3],[4,5,6]],L). we getL=[1,2,3,4,5,6]notL=[1,4,2,5,3,6]- Lin Jiayinappend/2, it may help you to get more familiar with lists of lists. - mat